C++ is allowed to remove copies. This is done in the return value optimization.
Update!
It turns out that I am wrong!
I was right at one point, but the C++ committee denied compilers the optimization in 1997. Whichever compiler I was remembering that did this was out of date, or doing it wrong, or possibly decided to ignore the committee. (I certainly can't see any reason for extra copies!)
In the updated summary, C++ is only allowed to elide (remove) a copy constructor operation for the return value optimization and for throwing and receiving exception objects.
Update 2
I am wrong again? Apparently I cannot read standards documentation properly?
GCC and Microsoft cl.exe both produce results without extra copies for temporaries.
Here is my test code, all Microsofted:
#include <stdio.h>
#include <tchar.h>
class A {
int m;
public:
A(int x=0) : m(x)
{
_putts(_T("Constructor A"));
}
A(const A &x) : m(x.m)
{
_putts(_T("Copy A"));
}
int get() const { return m; }
};
class B {
A m;
public:
B(int y=5) : m(y)
{
_putts(_T("Constructor B"));
}
B(const B &x) : m(x.m)
{
_putts(_T("Copy B"));
}
B(A x) : m(x)
{
_putts(_T("Construct B from A value"));
}
int get() const { return m.get(); }
};
class C {
A m;
public:
C(int y=5) : m(y)
{
_putts(_T("Constructor C"));
}
C(const C &x) : m(x.m)
{
_putts(_T("Copy C"));
}
C(const A &x) : m(x)
{
_putts(_T("Construct C from A reference"));
}
int get() const { return m.get(); }
};
int _tmain(int argc, _TCHAR* argv[])
{
_putts(_T("Hello World"));
int i = 27;
if( argc > 1 )
i = _tstoi(argv[0]);
A aval(i);
_tprintf(_T("A value is: %d\n"), aval.get());
B bval( aval );
_tprintf(_T("Value is: %d\n"), bval.get());
B bval2( (A(i)) );
_tprintf(_T("Value is: %d\n"), bval2.get());
C cval( aval );
_tprintf(_T("Value is: %d\n"), cval.get());
C cval2( (A(i)) );
_tprintf(_T("Value is: %d\n"), cval2.get());
_putts(_T("Goodbye World"));
return 0;
}
Use this to replace the includes for de-Microsofting for GCC:
#include <cstdio>
#include <cstdlib>
using namespace std;
#define _TCHAR char
#define _T(x) x
#define _tmain main
#define _putts puts
#define _tprintf printf
#define _tstoi atoi
Here is the output, same for both compilers:
Hello World
Constructor A
A value is: 27
Copy A
Copy A
Construct B from A value
Value is: 27
Constructor A
Copy A
Construct B from A value
Value is: 27
Copy A
Construct C from A reference
Value is: 27
Constructor A
Copy A
Construct C from A reference
Value is: 27
Goodbye World