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.
I think you are confusing NRVO
with RVO
.
NRVO
- Named return value optimizationRVO
- (unnamed) return value optimizationNRVO
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With