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.