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.