Reputation: 10480
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?
Upvotes: 2
Views: 87
Reputation: 254501
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.
Upvotes: 11