tags:
- Cpp
RVO in C++ (ENG)
Do this at first: Call Stack in C++ (ENG)
(U)RVO
the return value is a unnamed prvalue
since C++17, the compilers are required to provide URVO support
NRVO Named Return Value Optimization
the return value is a named lvalue
optional but recommended
you can turn off RVO using
-fno-elide-constructors
flags
for GCC and Clang
better performance than move constructor
disable flags applied
when the object construction happens outside the scope of the current function
// no RVO
Widget a = Widget(params);
Widget Process() {
return a;
}
// no RVO
Widget Process(Widget b{Widget(params)}) {
return b;
}
// NRVO
Widget Process() {
Widget c = Widget(params);
return c;
}
// URVO
Widget Process() {
return Widget(params);
}
the return type is not the same as what's being returned
CV qualifiers don't affect the RVO
When there are multiple return statements, returning different objects (for NRVO only), because at compile time, compiler doesn't know which branch is going to hit (is this real?)
When there's expressions only runs at run-time
When returning a complex expression (NRVO only)
std::move is a complex expression, ((expression) ? A : B) is also a complex expression
even a+=1 is a complex expression
For guaranteed URVO has no need to move or copy constructor required
If writing a copy/move constructor
Never make the constructor do anything else other than a copy/move
Because constructors can get elided
when the name of a non-volatile object:
// no RVO, volatile back-off any optimization
Widget example() {
Widget volatile a = Widget(1);
return a;
}