Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constructor initializer list is not calling copy constructor [duplicate]

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?

like image 250
Ankit singh kushwah Avatar asked Jun 20 '18 06:06

Ankit singh kushwah


People also ask

Does initializer list call copy constructor?

And if we use Initializer List there are only two function calls: copy constructor + destructor call.

Why is my copy constructor not being called?

It's because of copy elision optimization by the compiler. Adding -fno-elide-constructors option to g++ while compiling will disable that optimization.

Can I call constructor from copy constructor?

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.

Is assigned in constructor body consider performing initialization in initialization list?

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.


1 Answers

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.

like image 101
songyuanyao Avatar answered Oct 13 '22 12:10

songyuanyao