This code is calling another ctor in one ctor:
#include <iostream>
using namespace std;
class F {
public:
F() { cout << "ctor1\n"; }
F(int) { cout << "ctor2\n"; }
~F() { cout << "dtor\n"; }
};
class Foo {
F f;
public:
Foo() : f() { cout << "1\n"; }
Foo(int i) : f(i) { Foo(); cout << "2\n"; }
};
int main() {
Foo object(1);
return 0;
}
The result is:
ctor2
ctor1
1
dtor
2
dtor
It seems the member variable f destroyed twice here, is it Okay?
Here
Foo(int i) { Foo(); cout << "2\n"; }
You are not using delegating constructor. What you're doing is creating a temporary instance of Foo in the constructor body (and destroying it immediately).
The correct syntax for delegating constructor is
Foo(int i) : Foo() { cout << "2\n"; }
Related
I meet a course programming problem, which asks me to initialize the A a using passing by reference (initialize the A a in the func). How can I call A's constructor by A's reference?
#include <iostream>
using namespace std;
class A
{
public:
int x;
A()
{
cout << "default constructor" << endl;
x = 1;
}
A(int x)
{
cout << "constructor with param = " << x << endl;
this->x = x;
}
~A() {
cout << "destructor" << endl;
}
void print() {
cout << x << endl;
}
};
void fun(A& a)
{
a.A::A(10); // error!
return;
}
int main()
{
A a;
fun(a);
a.print();
return EXIT_SUCCESS;
}
There is a background of this problem. The teacher want us to replicate the NRVO(named return value optimization) result.
#include <iostream>
using namespace std;
class A
{
public:
int x;
A()
{
cout << "default constructor" << endl;
x = 1;
}
A(int x)
{
cout << "constructor with param = " << x << endl;
this->x = x;
}
~A() {
cout << "destructor" << endl;
}
void print() {
cout << x << endl;
}
};
A fun() {
A a = A(10);
return a;
}
int main()
{
A a = fun();
return EXIT_SUCCESS;
}
default g++ compiler:
constructor with param = 10
destructor
if we close the NRVO:
g++ test.cpp -fno-elide-constructors
constructor with param = 10
destructor
destructor
destructor
destructor
The teacher want us to replicate the NRVO(named return value optimization) result by passing by reference.
The syntax a.A::A(10); is incorrect.
Constructor is used to create an object of a class, you cannot call it on an already existing object. Even a constructor cannot be explicitly called. It is implicitly called by the compiler.
From general-1.sentence-2:
Constructors do not have names.
Thus, you cannot call a constructor explicitly. The compiler will automatically call the constructor when an object of that class-type is created.
You can not, not like this.
A reference always points to an initialized object. So you already failed before you called the function. The "return" argument is already initialized. And you can't initialized an initialized value again, not legally.
You can cheat by calling
std::construct_at(&a, 10);
For it to really reflect NRVO you could have something like this:
void fun(A *a)
{
std::construct_at(a, 10);
}
union UninitializedA {
std::byte uninitialized[sizeof(A)];
A a;
};
int main()
{
UninitializedA u;
fun(&u.a);
u.a.print();
u.a.~A();
return EXIT_SUCCESS;
}
I am learning C++14, in that come across this template variable feature and that interested me to dig more on this and i tried with multiple examples to understand the template variables. Say,
template <typename T>
T var;
var<int>;
var<float>;
Above code worked and it looked straight forward to understand too. But, when I tried to use class name in place of int or float as shown above, result in calling the temporary object creation for the class FOO and calling corresponding C'tor & dtor for the temp object.
var<FOO>; //FOO is a class
I have written a sample test program and its output for your understanding. My question is that,
Why var creates temp object?
How template variable differ for primitive datatypes and user defined datatypes?
If it is irrelevant or duplicate, please point me to the source for clear understanding.
Refer code below,
class B
{
public:
B()
{
std::cout<<"\nB ctor"<<std::endl;
}
B(const B& obj)
{
std::cout<<"B copy ctor"<<std::endl;
}
int operator()()
{
std::cout<<"operator() called"<<std::endl;
}
void f() {
//::A().print();
}
~B()
{
std::cout<<"\n~ for B()"<<std::endl;
}
};
//Declaring template variable
template<typename T>
T g ;
int main() {
g<int> = 30;
g<float> = 30.02f;
g<B> = B{};
std::cout<<"g value:"<<g<int><<std::endl;
std::cout<<"g value:"<<g<float>;
}
Output:
B ctor
g value:30
g value:30.02
~ for B()
No temporary object is created by this simple program:
int main() {
var<SomeClass>;
}
A temporary object is created here:
int main() {
var<SomeClass> = SomeClass{};
}
but that is because we did it with SomeClass{}. We then assigned that to the var<SomeClass> non-temporary object (global in many of your examples).
The code that runs here is
SomeClass::SomeClass()
SomeClass::SomeClass()
SomeClass::operator=(SomeClass&&)
SomeClass::~SomeClass()
SomeClass::~SomeClass()
in that order.
#include <iostream>
struct noisy {
noisy() { std::cout << __func__ << "()\n"; }
~noisy() { std::cout << __func__ << "()\n"; }
noisy(noisy&&) { std::cout << __func__ << "(&&)\n"; }
noisy(noisy const&) { std::cout << __func__ << "(c&)\n"; }
void operator=(noisy&&) { std::cout << __func__ << "(&&)\n"; }
void operator=(noisy const&) { std::cout << __func__ << "(c&)\n"; }
};
template<class T>
T var;
int main() {
std::cout << "Start of main\n";
{
var<noisy> = noisy{};
std::cout << "Body of main\n";
}
std::cout << "End of main\n";
}
live example.
Output:
noisy()
Start of main
noisy()
operator=(&&)
~noisy()
Body of main
End of main
~noisy()
lets say I have a class with 2 constructors like so:
class Foo
{
Foo(int x);
Foo();
...
}
I know that I can call one constructor from another like Foo() : Foo(42) {}, but why shouldn't (or should) I do the following:
Foo() {
Foo(42)
}
What is the difference in these cases?
Some suggest to use an "initializer" method, called from any constructor with their respective arguments, but I am puzzled as to what happens in the case above?
Let's put this example:
#include <iostream>
class B
{
private:
int number;
public:
B()
{
B(1);
}
B(int x) : number(x)
{
std::cout << "Constructor: " << x << std::endl;
}
void print(){
std::cout << "Msg: " << number << std::endl;
}
~B(){std::cout << "Destructor: " << number << std::endl;}
};
int main() {
B b;
b.print();
return 0;
}
Output:
Constructor: 1
Destructor: 1
Msg: 1
Destructor: 1
You are destroying a second object! This is strange, what happens if we use pointers...
#include <iostream>
class B
{
private:
int* arr;
public:
B()
{
B(1);
}
B(int x)
{
std::cout << "Constructor: " << x << std::endl;
arr = new int[x];
}
void print(int n){
std::cout << "Msg: " << arr[n] << std::endl;
}
void set(int n,int val){
arr[n] = val;
}
~B()
{
std::cout << "Destructor: " << arr << std::endl;
delete[] arr;
}
};
int main() {
B b;
b.set(0,14);
b.print(0);
return 0;
}
Constructor: 1
Destructor: 0xc45480
Msg: 14
Destructor: 0xc45480
Look up the pointer addr. They are the same, this means:
We are writing in deleted memory.
We are deleting the same memory twice.
These are two serious problems. You shouldn't do that.
Expression Foo(){Foo(42);} constructs anonymous temporary object that gets destroyed immediately without changing the object being constructed anyhow, while from Foo() : Foo(42){} will initialize the object being constructed.
You should not the following:
Foo() {
Foo(42)
}
When you are in the constructor body the member variables have been just constructed. That's why in C++ initialisation list exists.
The above code is semantically wrong! You are not absolutely using
delegating construction. Instead the statement Foo(42) in the body will just create another object without assigning it to any variable (anonymous variable).
You can imagine something like:
Foo() {
Foo another_obj = Foo(42);
}
In order to use delegating constructor, you must call constructor
in the initialisation list.
Foo() : Foo(42) { }
I am writing code to access private members of a class through another friend class. The below code works
// Example program
#include <iostream>
#include <string>
using namespace std;
class Foo
{
private:
int a;
protected:
public:
friend class Bar;
Foo(int x)
{
a = x ;
}
};
class Bar
{
private:
protected:
public:
int b;
Bar(Foo& f)
{
b = f.a;
cout << "f.a is " << f.a << endl;
}
};
int main()
{
Foo foo(5);
Bar bar(foo);
cout << "Value of variable b is " << bar.b << endl;
}
Above code works fine. However, if I want to access a private variable of Foo through a function in friend class Bar, I am unable to. See code below
#include <iostream>
#include <string>
using namespace std;
class Foo
{
private:
int a;
protected:
public:
friend class Bar;
Foo(int x)
{
a = x ;
}
};
class Bar
{
private:
protected:
public:
int b;
Bar(Foo& f)
{
b = f.a;
}
void printvariable(void)
{
cout << "f.a is " << f.a << endl;
}
};
int main()
{
Foo foo(5);
Bar bar(foo);
cout << "Value of variable b is " << bar.b << endl;
}
I totally understand why execution fails on the
void printvariable(void)
{
cout << "f.a is " << f.a << endl;
}
function since f is not in scope for the function. However, since I am passing Foo f in the constructor for Bar b, I am hoping to write code that will allow me to access members in Foo without passing Foo f to the function printvariable() again.
What is the most efficient way to write this code?
You can keep the reference to f. The code should be:
class Bar
{
private:
protected:
public:
int b;
Foo& f_ref;
Bar(Foo& f)
:f_ref(f)
{
b = f.a;
}
void printvariable(void)
{
cout << "f.a is " << f_ref.a << endl;
}
};
TEST!
You can do it like this, but if I were you I'd write some getters, also – class friendship isn't really recommended.
class Bar {
public:
Foo& ref;
Bar(Foo& f)
: ref { f }
{ }
void printvariable() {
cout << "f.a is " << ref.a << endl;
}
};
Btw there's no reason to add void in brackets in C++, it lost its meaning from C and has no effect by now.
You are wrong in one point. You are indeed passing a reference to f in the ctor, but the constructor and whole class Bar does not remember a whole object of f. In your original code, the constructor only makes the Bar object remember the int a part of the object, so only that little bit is later accessible:
class Foo
{
...
friend class Bar;
...
};
class Bar
{
...
int b;
Bar(Foo& f)
{
b = f.a; // <=--- HERE
}
void printvariable(void)
{
cout << "f.a is " << b << endl; // <-- now it refers B
}
Please note how your ctor of Bar only reads f.a and stores it in b. From now on, the Bar object only remembers b and that's all. You can freely access the b in printvariable. However, it will not be the a-taken-from-f. It will be b, that was set to the same value as f.a during constructor. Since that point of time, b and f.a are totally separate. That's how value copying works.
To make Bar remember whole f, you have to, well, remember whole f:
class Bar
{
...
Foo wholeThing;
Bar(Foo& f)
{
wholeThing = f; // <=--- HERE
}
void printvariable(void)
{
cout << "f.a is " << wholeThing.a << endl;
}
However, again, there's a catch: now since wholeThing is of type Foo, the constructor will actually make a copy of that object during wholeThing=f. Just the same as it was when b=f.a, but now it remembers a copy of whole f.
Of course, it's only matter of type. You can store a reference instead of whole-Foo, but it needs a bit different initialization syntax:
class Bar
{
...
Foo& wholeThing;
Bar(Foo& f) :
wholeThing(f) // <=--- HERE
{
// <=--- empty
}
void printvariable(void)
{
cout << "f.a is " << wholeThing.a << endl;
}
In the code show below, how do I assign rvalue to an object A in function main?
#include <iostream>
using namespace std;
class A
{
public:
int* x;
A(int arg) : x(new int(arg)) { cout << "ctor" << endl;}
A(const A& RVal) {
x = new int(*RVal.x);
cout << "copy ctor" << endl;
}
A(A&& RVal) {
this->x = new int(*RVal.x);
cout << "move ctor" << endl;
}
~A()
{
delete x;
}
};
int main()
{
A a(8);
A b = a;
A&& c = A(4); // it does not call move ctor? why?
cin.ignore();
return 0;
}
Thanks.
Any named instance is l-value.
Examples of code with move constructor:
void foo(A&& value)
{
A b(std::move(value)); //move ctr
}
int main()
{
A c(5); // ctor
A cc(std::move(c)); // move ctor
foo(A(4));
}