Home > Software design >  Is the move or the copy constructor used when passing a list into a direct initialization?
Is the move or the copy constructor used when passing a list into a direct initialization?

Time:06-03

Given the following toy code:

class P  // with compiler-generated copy constructor and move constructor
{
public:
    P(int x, int y) { }
};

int main()
{
    P p({x,y});
}

In my current understanding, the {x,y} in P p({x,y}); is converted into an object of type P by implicitly calling the constructor P::P(int x, int y) and passing x and y to it. Usually there is optimization so that this P object is directly constructed as p. Nevertheless, may I ask if this implicit call of P::P(int x, int y) is invoked by the move constructor or the copy constructor (generated by the compiler)?

CodePudding user response:

Usually there is optimization so that this P object is directly constructed as p. Nevertheless, may I ask if this implicit call of P::P(int x, int y) is invoked by the move constructor or the copy constructor

Let's see what happens here with and without optimizations in C 17 and prior to C 17.

Prior C 17

Prior to C 17 there was non-mandatory copy elision, which means when you wrote:

P p({x,y}); //here a temporary of type X will be created and then moved/copied 

In the above statement, prior to C 17 a temporary of type P will be created which will then be copied/moved using the copy/move constructor. That is the temporary created will be used to copy/move construct p. Since in your example, the compiler will implicitly generate a move constructor, it will be used instead of the implicitly generated copy constructor since a temporary prvalue is used to construct p. It is as-if you wrote:

P p(P{x, y}); //equivalent to what happens without optimization in prior C  17

Note that compilers are allowed to elide this copy/move construction. Thus if you want to see which constructors are called then you can make use of the -fno-elide-constructor that will disable this non-mandatory copy elison. The output of the program with -fno-elide-constructors prior to C 17 is:

parameterized ctor
move ctor

Again if you don't supply the -fno-elide-constructors flag then the compiler will elide this move construction and you will see the output:

parameterized ctor

C 17 & Onwards

From C 17 there is mandatory copy elision. This means there will be no creation of temporary involve here. The object x will be directly constructed as-if you wrote:

P p(x, y); // this is equivalent to what you wrote from C  17 due to mandatory copy elison

That is, from C 17 onwards, there will be no creation of temporary of type P. This means, the flag -fno-elide-constructors will have no effect in your example from C 17.

We're guaranteed that there is no call to the copy/move constructor from C 17.

  • Related