Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is RVO applied on this situation?

Tags:

c++

c++11

rvo

nrvo

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.

like image 545
user2296145 Avatar asked Dec 03 '16 17:12

user2296145


2 Answers

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.

like image 165
Galik Avatar answered Oct 27 '22 04:10

Galik


NRVO and RVO are different cases of elision.

Elision is where the lifetimes of multiple objects are merged into one object.

The names NRVO and RVO are names for how the compiler does elision when the standard permits it.

Elision is permitted in your example between the temporary created on the return line, the return value of the function, and the named variable you store the return value in. Every serious compiler can and will elide those values together, unless you explictly tell it not to via compiler flags. And in C++17 those elisions will be mandatory.

like image 23
Yakk - Adam Nevraumont Avatar answered Oct 27 '22 02:10

Yakk - Adam Nevraumont