I was pretty sure the calling of B(A()) will call the defined constructor of B in my code.
But I was surprised to find out that it didn't call to my constructor B and of course didn't print "Constructor B".
So, to which constructor this code is calling (what is the signature of this constructor that it's calling to)?
struct A
{
};
struct B
{
B(const A a) { std::cout << "Constructor B" << std::endl; }
};
int main()
{
B(A());
return 0;
}
It doesn't construct an object with type B as you expected, then no constructor is called.
When declaring variables we can add (unnecessary) parentheses around the variable name, i.e. int (a); has the same effect as int a;. Similarly, B(A()); is same as B A();, which declares a function named A, which takes no parameters and returns B.
As the workaround you can change () to {}, e.g.
B(A{});
B{A()};
B{A{}};
LIVE
Related
I read in http://www.cs.technion.ac.il/users/yechiel/c++-faq/init-lists.html
that using initializer lists is more efficient than doing assigment in the body of the constructor, because for example in Fred::Fred() { x_ = whatever; }
1) the expression whatever causes a separate, temporary object to be created, and this temporary object is passed into the x_ object's assignment operator. Then that temporary object is destructed at the ;
2)the member object will get fully constructed by its default constructor, and this might, for example, allocate some default amount of memory or open some default file
How can assigment cause the creation of some temporary object inside the constructor? That means that the Construtor would call itself: an infinite recursive call
I made the following piece of code to verify a copy of the object is created in the assigment process,hoping to see the additional creation and destruction of the temporary object but all I can see is the creating and destruction of the object I am creating in the main an of course no infinite recursive call.
How do I make sense of it and how can I modify the code to see the creation and destruction of the temporary object?
#include<iostream>
using namespace std;
class Base
{
private:
int c_var;
public:
Base( )
{ c_var=10;
cout <<"Constructor called"<<endl;
cout << "Value is " << c_var<<endl;
}
~Base()
{
cout <<"Destructor called"<<endl;
}
};
int main()
{
Base il;
}
How can assigment cause the creation of some temporary object inside the constructor? That means that the Construtor would call itself: an infinite recursive call
No. The text talks about calling the constructor of the member. With an int it doesn't matter too much, but consider:
struct foo {
foo() {
/* construct a foo, with expensive instructions */
std::cout << "default constructor";
}
foo(int x) {
/* also construct a foo */
std::cout << "constructor";
}
};
struct bar_wrong {
foo f;
bar_wrong() {
f = foo(42);
}
};
Members are initialized before the body of the constructor is executed. Hence the foo member of bar_wrong will first be default constructed (which is potentially expensive) just to be overwritten with the right instance later and creating a bar_wrong will print both outputs from foos constructors.
The correct way is
struct bar_correct {
foo f;
bar_correct() : f(42) {}
};
Because here foo is only initialized. Alternatively you can use in-class initializers:
struct bar_alternative {
foo f{42};
};
Here the compiler generated constructor is sufficient. It will use the in-class initializer to initialize f with 42.
Consider the following code
#include <iostream>
using namespace std;
class A
{
int x;
public:
A() { cout << "A's constructor called " << endl; }
};
class B
{
public:
static A a;
B() { cout << "B's constructor called " << endl; }
static A getA() { return a; }
};
A B::a; // definition of a
int main()
{
B b1, b2, b3;
A a = b1.getA();
cout<<&a<<endl;
cout<<&B::a;
return 0;
}
the output is
A's constructor called
B's constructor called
B's constructor called
B's constructor called
0x7fff03081280
0x601194
Now lets consider another similar code
#include <iostream>
using namespace std;
class A
{
int x;
public:
A() { cout << "A's constructor called " << endl; }
};
class B
{
public:
static A a;
B() { cout << "B's constructor called " << endl; }
static A getA() { return a; }
};
A B::a; // definition of a
int main()
{
B b1, b2, b3;
A a ;
a= b1.getA();
cout<<&a<<endl;
cout<<&B::a;
return 0;
}
the output is
A's constructor called
B's constructor called
B's constructor called
B's constructor called
A's constructor called
0x7ffc485a1070
0x601194
Now my question is that why in the first case the constructor of A is called only once , whereas in the second code its called twice.
Also the two output &a and &B::a are different so it means they are two different objects .
Please explain why this is so.
In your first code
A a = b1.getA();
the copy-constructor of A gets called which doesn't generate any output. Define it yourself and you'll get a similar output to your second code.
Hmm, B::a is B's (public) static member instance of otherwise quite an usual class A. So, the first A's constructor logged is that of B::a, which should be initialized before control enters main, but next you create a separate instance of A local to main, it is constructed in order alongside with other main's local variables (here, right after all the Bs) and it is naturally distinct from B::a.
Now my question is that why in the first case the constructor of A is called only once , whereas in the second code its called twice.
Because in the first case you default-initialised only the static B::a, and copy-initialised the local a.
In the second you default-initialised both objects.
The crucial difference is that you only print a message in the default constructor, and don't print anything in the copy constructor.
Also the two output &a and &B::a are different so it means they are two different objects .
That is correct. a is a local variable, while B::a is a static member variable. They are different objects.
Static member variables of class type represent a storage with process-wide life span. It gets initialized as such, at some point before entry point to program - the beginning of main() - is reached. That's the first constructor call.
The line
A a = b1.getA();
initializes object a by calling copy constructor and through return value optimization and copy elision there is no default constructor call.
The second variant:
A a; // A() call
a = b1.getA(); // operator= call
Modified class
class A
{
int x;
public:
A(const A& a): x(a.x) { cout << "A's copy constructor called " << endl; }
A(A&& a): x(a.x) { a.x = 0; cout << "A's move constructor called " << endl; }
const A& operator=(const A& a) { x = a.x; cout << "A's copy operator= called " << endl; }
A() { cout << "A's constructor called " << endl; }
};
would give this output in first case:
A's constructor called
B's constructor called
B's constructor called
B's constructor called
A's copy constructor called
And second case would result in:
A's constructor called
B's constructor called
B's constructor called
B's constructor called
A's constructor called
A's copy constructor called
A's copy operator= called
It is simple to understand that whenever the class instance (object) getting created associated constructor is getting called.
Now my question is that why in the first case the constructor of A is called only once , whereas in the second code its called twice.
You are creating second object directly in stack and constructor is getting called in later case, first one is the static and second one by creating object in stack by below statement.
A a ;
In first case, instead of constructor, copy constructor is getting called so thats why you are not getting the print statement second time.
A a = b1.getA();
I have always thought that base class constructors/destructors/friends are not inherited by derived class. This link confirms this :
http://www.geeksforgeeks.org/g-fact-4/.
I was also aware that we can write base class constructors in the initialization list of derived class initializer list.
Having said that: I tried to check my skills today about it. But I failed to guess the output of this program.
#include<iostream>
class A {
int x, y;
public:
A(int a = 0, int b = 0) : x(a), y(b) {
std::cout << "A ctor called" << std::endl;
}
void print_A() {
std::cout << "x = " << x << std::endl;
std::cout << "y = " << y << std::endl;
}
};
class B : public A {
int z;
public:
// I knew that A member can be initilized like this.
B(int a = 0, int b = 0, int c = 0) : z(a), A(b, c) {
std::cout << "C ctor called" << std::endl;
// I was not aware about that.
A(b, c);
}
void print_B() {
std::cout << "z = " << z << std::endl;
}
};
int main() {
B b(1, 2, 3);
b.print_A();
b.print_B();
}
Output :
A ctor called
C ctor called
A ctor called
x = 2
y = 3
z = 1
Couple of questions:
If constructors/desctructors/friends are not inherited from base, how can class 'B' is able to access constructor of class 'A' here.
How come you get this output? How come two constructors of 'A' have been called.
Your understanding is faulty. This:
// I was not aware about that.
A(b, c);
doesnt initialise the A member of B, it (notionally at least) creates a temporary, nameless local variable in the body of the constructor, somewhat analogous to if you had said:
A a(b, c);
The constructor for A is a public member, so anything can call it.
If constructors/desctructors/friends are not inherited from base, how can class 'B' is able to access constructor of class 'A' here?
"Not inherited" does not mean "inaccessible to the derived class". A derived class can certainly reference a base constructor. B's constructor does it twice:
The first access is in the initialization list
The second access is in the body of B's constructor; it creates a temporary object
Inheriting a constructor would mean that users of B would be able to access B(int, int), which they cannot do*.
It seems like a constructor call. Why does it create a temporary object?
Consider this method:
void foo(const A& a);
A common way is to call it like this:
A a(1, 2);
foo(a);
but C++ also lets you call it without creating A on a separate line:
foo(A(1, 2));
In this case C++ creates a temporary object, and passes foo a reference to it. When you write
A(1, 2)
C++ also creates a temporary object for you by calling its constructor.
How come two constructors of 'A' have been called.
The constructor is invoked twice; that is why you get the output.
* C++11's using mechanism allows you to achieve an effect very similar to constructor inheritance, provided that you follow specific rules.
the constructor is called by the every time A(b, c) is called;
you are calling it on line
B(int a = 0, int b = 0, int c = 0) : z(a), A(b, c) {
and you are calling it inside the b constructor
// I was not aware about that.
A(b, c);
the code works as intended
If constructors/desctructors/friends are not inherited from base, how can class 'B' is able to access constructor of class 'A' here.
You mean on these lines?
// I was not aware about that.
A(b, c);
It isn't "accessing the constructor" in the sense you think. It just creates (and immediately discards) an anonymous temporary A in the body of the constructor function.
How come you get this output? How come two constructors of 'A' have been called.
Because you created two instances of A: the base-class subobject of B b, and the anonymous temporary.
Here's an easy experiment to verify this, with the following logging:
// in A
A(int a = 0, int b = 0) : x(a), y(b) {
std::cout << "A::A #" << static_cast<void*>(this) << std::endl;
}
~A() {
std::cout << "A::~A #" << static_cast<void*>(this) << std::endl;
}
// in B
B(int a = 0, int b = 0, int c = 0) : z(a), A(b, c) {
std::cout << "B::B #" << static_cast<void*>(this) << std::endl;
A(b, c);
}
~B() {
std::cout << "B::~B #" << static_cast<void*>(this) << std::endl;
}
I get output something like
A::A #0xffec7054
B::B #0xffec7054
A::A #0xffec704c
A::~A #0xffec704c
x = 2
y = 3
z = 1
B::~B #0xffec7054
A::~A #0xffec7054
See that the instance address of the second A::A is different from the first (so it's a different object), and it's followed by an A::~A (because the anonymous temporary goes immediately out of scope).
Notes:
If you could "call the constructor" as you suggested originally, it would look something like
auto subobject = static_cast<A*>(this);
new (subobject) A(b, c);
and would be very wrong. The A subobject of b was completely constructed when it's own constructor completed, before the body of B's constructor starts. You can't just re-create a new object in the same space, what would happen to the old one?
This may seem trivial, but for objects with dynamically-allocated resources, it would be a serious bug. It's not allowed.
You wrote your initializer list : z(a), A(b, c), but should be aware the base-class subobject will be constructed before the derived-class members are initialized. That is, those two things will happen in the opposite order to what you wrote. It's not (necessarily) an error, but it's worth knowing.
So I'm just getting caught up in some nuisances of C++. Specifically, passing anonymous variables by reference for use in an initializer list for a class in C++. Consider the following code;
class A {
public:
int x;
A(int x=0) : x(x) {
std::cout <<"A: creatred\n";
}
~A() {
std::cout << "A: destroyed\n";
}
};
class B {
public:
A a;
B(const A& in) : a(in) {
std::cout <<"B: creatred\n";
}
~B() {
std::cout << "B: destroyed\n";
}
};
int main() {
B b(A(0));
std::cout << "END\n";
return 0;
}
outputs:
A: creatred
B: creatred
A: destroyed
END
B: destroyed
A: destroyed
I count 2 creations and 3 destructions. What's going on? Way I see it, I'm using an anonymous variable A(0) as input when creating b. Not sure what the order of things are now. A reference to the anonymous variable is created and used to copy (the copy constructor will be called in the initializer list, yes?) the member variable a. When is the anonymous variable destroyed? And in general, why am I seeing 2 constructors called and 3 destructors. Thanks.
You didn't override A's copy constructor to print a message...
Specifically, a(in) invokes it.
The missing constructor would be the copy constructor for A.
You copy construct A in the below line.
B(const A& in) : a(in)
A: destroyed
END
This is the temporary being destroyed, it is destroyed at the end of the line
B b(A(0));
My understanding of constructor chaining is that , when there are more than one constructors in a class (overloaded constructors) , if one of them tries to call another constructor,then
this process is called CONSTRUCTOR CHAINING , which is not supported in C++ .
Recently I came across this paragraph while reading online material.... It goes like this ...
You may find yourself in the situation where you want to write a member function to re-initialize a class back to default values. Because you probably already have a constructor that does this, you may be tempted to try to call the constructor from your member function. As mentioned, chaining constructor calls are illegal in C++. You could copy the code from the constructor in your function, which would work, but lead to duplicate code. The best solution in this case is to move the code from the constructor to your new function, and have the constructor call your function to do the work of initializing the data.
Does a member function calling the constructor also come under constructor chaining ??
Please throw some light on this topic in C++ .
C++11 allows constructor chaining (partially). This feature is called "delegating constructors". So in C++11 you can do the following
class Foo
{
public:
Foo(int a) : Foo() { _a = a; }
Foo(char* b) : Foo() { _b = b; }
Foo() { _c = 1.5; }
private:
int _a = 0;
char* _b = nullptr;
double _c;
};
However, there is a severe limitation that a constructor that calls another constructor is not allowed to initialize any other members. So you cannot do the following with a delegating constructor:
class Foo
{
public:
Foo(int a) : Foo(), _a(a) { }
Foo(char* b) : Foo(), _b(b) { }
Foo() { _c = 1.5; }
private:
int _a = 0;
char* _b = nullptr;
double _c;
};
MSVC++2013 gives compile error "C3511: a call to a delegating constructor shall be the only member-initializer" for the latter code example.
The paragraph basically says this:
class X
{
void Init(params) {/*common initing code here*/ }
X(params1) { Init(someParams); /*custom code*/ }
X(params2) { Init(someOtherParams); /*custom code*/ }
};
You cannot call a constructor from a member function either. It may seem to you that you've done it, but that's an illusion:
class X
{
public:
X(int i):i(i){}
void f()
{
X(3); //this just creates a temprorary - doesn't call the ctor on this instance
}
int i;
};
int main()
{
using std::cout;
X x(4);
cout << x.i << "\n"; //prints 4
x.f();
cout << x.i << "\n"; //prints 4 again
}
That's not what the text says. It's suggesting your constructor call a member function which is normal and legal. This is to avoid explicitly calling the ctor again and to avoid duplicating code between your ctor and reset function.
Foo::Foo() {
Init();
}
void Foo::Reset() {
Init();
}
void Foo::Init() {
// ... do stuff ...
}
I'm not sure if it (calling a constructor from a member function) will work or not, but it's a bad practice. moving the initialize code to a new function is the logic way.
Basically saying, Don't call the constructor unless you constructing...
when we call constructor from a member function, then it will temporary create a object of its type.
in case if we are calling in derived class function then all the parent constructors are also gets executed and destroyed using destructor once function goes out of scope.
its not a Good Practice to call the constructors in member functions since it creates objects of every class derived.