Consider the following code:
#include
using namespace std;
class A
{
public:
int a;
A(): a(5)
{
cout &l
#include <iostream>
using namespace std;
class A
{
public:
int a;
A(): a(5)
{
cout << "Constructing: " << (void *)this << std::endl;
}
A(const A &b)
{
a = b.a;
cout << "Copy Constructor: " << (void *)this << " from " << (void *)&b << std::endl;
}
A fun(A a)
{
return a;
}
};
int main()
{
A a, c;
A b = a.fun(c);
std::cout << "a:" << (void *)&a << std::endl <<
"b:" << (void *)&b << std::endl <<
"c:" << (void *)&c << std::endl;
return 0;
}
Yields:
Constructing: 0x7fffbb377220
Constructing: 0x7fffbb377210
Copy Constructor: 0x7fffbb377230 from 0x7fffbb377210
Copy Constructor: 0x7fffbb377200 from 0x7fffbb377230
a:0x7fffbb377220
b:0x7fffbb377200
c:0x7fffbb377210
So it constructs a
, constructs c
, copies c
to an intermediate (argument a
of the function), and then copies the intermediate directly into b
, skipping the typical copying of a to a return intermediate. This is even better demonstrated if you pass by value (change to A fun(const A& a)
:
Constructing: 0x7fff8e9642b0
Constructing: 0x7fff8e9642a0
Copy Constructor: 0x7fff8e964290 from 0x7fff8e9642a0
a:0x7fff8e9642b0
b:0x7fff8e964290
c:0x7fff8e9642a0
a is constructed, c is constructed, c is copied directly to b, despite b not being passed to fun!
The copy that is elided is the copy of the temporary return value into b
. Without elision the return value is initialized from a
and copied to b
. Instead, the temporary that would otherwise hold the return value is constructed into b
and initialized with a
. [class.copy]/31:
when a temporary class object that has not been bound to a reference (12.2) would be copied/moved to a class object with the same cv-unqualified type, the copy/move operation can be omitted by constructing the temporary object directly into the target of the omitted copy/move
You can observe this if you add an additional output in fun
:
A fun(A a)
{
cout << "fun!" << endl;
return a;
}
Then with the elision you'll get
[…]
fun!
Copy Constructor
And without:
[…]
fun!
Copy Constructor
Copy Constructor