Consider the following code:
#include <iostream>
using namespace std;
class A
{
public:
int a;
A(): a(5)
{
cout << "Constructor\n";
}
A(const A &b)
{
a = b.a;
cout << "Copy Constructor\n";
}
A fun(A a)
{
return a;
}
};
int main()
{
A a, c;
A b = a.fun(c);
return 0;
}
The output of the above code with g++ file.cpp
is:
Constructor
Constructor
Copy Constructor
Copy Constructor
The output of the above code with g++ -fno-elide-constructors file.cpp
is:
Constructor
Constructor
Copy Constructor
Copy Constructor
Copy Constructor
I know Return Value Optimization. My question is which call to copy constructor is elided(temporary object during returning or returned object being copied to b)?
If the elided copy constructor is the one used for creating b, then how is b created at all (because there is no constructor call in this case also)?
If I replace the line A b = a.fun(c);
with a.fun(c)
and compile using the first method or even the second method, then also the copy constructor is being called 2 times . So, if in the case explained in the previous paragraph, the temporary object's copy constructor is elided, then why isn't it elided in this case?
The copy that is elided is the copy of the temporary return value into
b
. Without elision the return value is initialized froma
and copied tob
. Instead, the temporary that would otherwise hold the return value is constructed intob
and initialized witha
. [class.copy]/31:You can observe this if you add an additional output in
fun
:Then with the elision you'll get
And without:
Yields:
So it constructs
a
, constructsc
, copiesc
to an intermediate (argumenta
of the function), and then copies the intermediate directly intob
, skipping the typical copying of a to a return intermediate. This is even better demonstrated if you pass by value (change toA fun(const A& a)
:a is constructed, c is constructed, c is copied directly to b, despite b not being passed to fun!