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.
