2

Why does this example print:

#include <iostream> struct X { X() = default; X(X const&) { std::cout << "copy-constructor\n"; } X(X&&) { std::cout << "move-constructor\n"; } X& operator=(X) { return *this; } }; int main() { X x, y; std::cout << "assign from prvalue calls the "; x = X{}; std::cout << "\nassign from xvalue calls the "; x = std::move(y); } 

assign from prvalue calls the
assign from xvalue calls the move-constructor

Both X{} and std::move(y) are rvalues so why does only assigning to X{} cause copy-elision?

4
  • 2
    implement X& operator=(const X&) and X& operator=(X&&), and you will see Commented Mar 9, 2015 at 14:12
  • @BЈовић But they will be ambiguous with my assignment operator. Commented Mar 9, 2015 at 14:14
  • Yes, remove your assignment operator Commented Mar 9, 2015 at 14:16
  • Are you asking why the move constructor is not elided? Commented Mar 9, 2015 at 14:23

1 Answer 1

11

Copy elision works in the first case because you're initialising the assignment operator's parameter from a temporary; the temporary can be omitted, constructing the parameter directly instead. In the words of the standard, one of the criteria for elision is:

when a temporary class object that has not been bound to a reference 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

In the second case, you're not initialising it from a temporary, but from an existing object. It has already been constructed, in a different location to the target, so the optimisation described above can't be done.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.