So I was learning about constructor initializer list and I wrote the following code :
class Mango
{
public:
Mango(){cout<<"Mango::ctor()";}
Mango(const Mango& other){cout<<"Mango::copy_ctor()";}
};
class Box
{
public:
Box() : mango(Mango()) //**doesn't call copy constructor**
{
}
Mango mango;
};
int main()
{
Box box;
return 0;
}
I used g++ compiler for this. Its calling the constructor not copy constructor. It should call copy constructor right because I am creating an object to create another object? What's the issue here and what does standard says about it?
And if we use Initializer List there are only two function calls: copy constructor + destructor call.
It's because of copy elision optimization by the compiler. Adding -fno-elide-constructors option to g++ while compiling will disable that optimization.
The answer is No. The creation of the object memory is done via the new instruction. Copy constructor is then in charge of the actual copying (relevant only when it's not a shallow copy, obviously). You can, if you want, explicitly call a different constructor prior to the copy constructor execution.
Note: It is mandatory that a reference or a const member must be intialized in a constructor initialization list. They cannot be 'assigned' in the body of the constructor.
Because of copy elision, the copy-construction is omitted here. This behavior is guaranteed from C++17. Before C++17 it's not mandatory; the compilers are permitted, but not required to perform copy elision1.
Under the following circumstances, the compilers are required to omit the copy- and move- construction of class objects even if the copy/move constructor and the destructor have observable side-effects. They need not be present or accessible, as the language rules ensure that no copy/move operation takes place, even conceptually:
In initialization, if the initializer expression is a prvalue and the cv-unqualified version of the source type is the same class as the class of the destination, the initializer expression is used to initialize the destination object:
T x = T(T(T())); // only one call to default constructor of T, to initialize x
That means, mango
will initialized by the default constructor directly.
[1] In fact most implementations would also perform copy elision before C++17. With Gcc you can try with -fno-elide-constructors
option in pre-C++17 mode to disable copy elision.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With