Search code examples
c++c++11rvo

I'm returning non-named object from a function. Why RVO still kicks in?


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?


Solution

  • 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.