C++ move assignment triggers move constructor first

c++

Solution

The "extra object" is called the return value. When returning a value from a function; this value is copy/move constructed from the value you supplied to the `return` statement.

Often this undergoes copy elision which may explain why you didn't recognize it. When copy elision happens, the line `C tmp;` will actually construct `tmp` directly into the return value. Copy elision can also occur in some other situations; for the full text see C++11 [class.copy]#31.

Presumably you either manually disabled copy elision here, or the compiler decided it was a good idea not to perform copy elision. Update: Your compiler does this particular copy-elision only on Release builds - thanks Praetorian

Problem

``` #include <iostream> class C { public: ~C() { std::cout << this << " destructor\n"; } C() { std::cout << this << " constructor\n"; } C(C&& rhs) { std::cout << &rhs << " rhs\n"; std::cout << this << " move constructor\n"; } C& operator=(C&& rhs) { std::cout << &rhs << " rhs\n"; std::cout << this << " move assignment\n"; return *this; } }; C make_one() { C tmp; return tmp; } int main() { std::cout << "move constructor:\n"; C c1(make_one()); std::cout << &c1 << " &c1\n\n"; std::cout << "move assignment:\n"; C c2; c2 = make_one(); ... } ``` Output: ``` move constructor: 000000000021F9B4 constructor // tmp constructed in make_one() 000000000021F9B4 rhs // return triggers tmp being passed to ... 000000000021FA04 move constructor // ... c1's move constructor (see below) 000000000021F9B4 destructor // tmp destructs on going out of scope 000000000021FA04 &c1 // (confirmed c1's address) move assignment: 000000000021FA24 constructor // c2 constructed 000000000021F9B4 constructor // tmp constructed in make_one() again 000000000021F9B4 rhs // tmp passed to ... 000000000021FA34 move constructor // ... a new object's move constructor 000000000021F9B4 destructor // tmp destructs on going out of scope 000000000021FA34 rhs // new object passed to ... 000000000021FA24 move assignment // .. c2's move assignment operator 000000000021FA34 destructor // new object destructs ... ``` The move assignment appears to trigger the move constructor first and create an extra object. Is this normal? I would have expected (by analogy with copy assignment) for tmp to be passed straight to c2's move assignment. [Visual Studio Express 2013]

Original source