Search code examples
c++c++11rvonrvo

Is RVO applied on this situation?


Let's say we have this situation

std::string v_1()
{
    return "name";
}
std::string test = v_1();

Is RVO applied here? I think that the answer is no, because one the rules to apply RVO is: "If a function returns a class type by value, and the return statement's expression is the name of a non-volatile object with automatic storage duration, which isn't the function parameter, or a catch clause parameter, and which has the same type (ignoring top-level cv-qualification) as the return type of the function, then copy/move is omitted" And in this situation the object returned does not have the same type of the return type of the function, but I'm not 100% that RVO is not applied here.

Thank you very much.

PS. On this talk https://www.youtube.com/watch?v=AKtHxKJRwp4 (minute 40, second 18) Stephan, from Microsoft, talks about a situation where RVO cannot be applied because the return type of the function is different than the type of the returned object (in his example a tuple vs a pair). I think that the same principle applies here.


Solution

  • I think you are confusing NRVO with RVO.

    • NRVO - Named return value optimization
    • RVO - (unnamed) return value optimization

    NRVO involves a named variable whereas RVO involves unnamed temporaries that are constructed in the return statement.

    The example on the video is NRVO where the named object obviously can't be constructed on the caller stack when the types are different because there has to exist one object of one type in the function's stack and another object of the other type on the caller's stack.

    Your example is RVO where you are not using a pre-constructed named object. In your code you are constructing a temporary object as a return value. Because it is a temporary the rule you quoted does not apply.

    According to the C++11 standard I see no reason why RVO can not occur:

    12.8 Copying and moving class objects [ class.copy ] ... 31 ...

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

    By returning a char array a temporary std::string is constructed and that is what gets returned to the caller.