Regarding this: Why does std::move prevent RVO? someone wrote that: "Hence in a return statement copy elision can only occur, if the expression is the name of a local variable"
However I made a little test with GCC:
class X
{
public:
X()
{
cout << "def" << endl;
}
X(const X& x)
{
cout << "copy" << endl;
}
X(X&& x)
{
cout << "move" << endl;
}
};
X produceX()
{
return X();
}
int main()
{
X x{produceX()};
return 0;
}
The produceX function does not return a named value. It returns an unnamed temporary object. However the RVO still kicks and there is no copy nor move construction. The x object from main is constructed in-place. If I write produceX like this:
X produceX()
{
X localNamedObject;
return localNamedObject;
}
it behaves the same way (which is expected). But why RVO is allowed in the former case?
That statement is an over-simplification, although the answer you took it from does in fact answer this question, and provides the relevant text from the standard.
Copy elision is allowed when returning a temporary (as a general case of using a temporary to initialise an object of the same type), as well as when returning a local variable.
It's also allowed when throwing and catching exceptions by value, but that's beyond the scope of this question.