c++rvaluervo

return rvalue of temporary as value


So, I have the following class:

class Foo {
public:
    Bar &&bar() {
        return std::move(_bar);
    }
private:
    Bar _bar;
}

I know that it is valid to use this class in the following context:

Bar bar;
{
    Foo foo;
    bar = foo.bar(); // bar is move-assigned, as foo is still in scope
}

Now, the situation I an wondering about is: what happens if I directly return bar from a method, without storing it beforehand:

Bar testFunc() {
    Foo foo;
    return foo.bar();
}

Bar test = testFunc();
// is test now valid?

I think that this should be theoretically fine, as testFunc returns a value that is constructed from the rvalue before foo is destroyed - but is this still the case if the compiler applies return-value-optimization?

I guess I am a little confused how exactly this works...


Solution

  • is test now valid?

    The code should be valid as long as the moved-from object is not accessed.

    but is this still the case if the compiler applies return-value-optimization?

    Bar testFunc() {
        Foo foo;          // Bar is constructed here
        return foo.bar(); // prvalue is move-constructed and copy elided
    }
    Bar test = testFunc(); // default ctor + move ctor (one copy elision)
    

    In total one copy elision is performed.

    Moving out a member seems like a code smell. It is hard to judge without knowing the concrete usage, but maybe:

    Bar make_bar(const Foo& foo) {
        Bar bar;
        // init bar as needed
        return bar;
    }
    

    This way both calls will result in RVOs.