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

When does the RVO not working?

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

Warnings

If writing a copy/move constructor

Never make the constructor do anything else other than a copy/move

Because constructors can get elided

hh

when the name of a non-volatile object:

// no RVO, volatile back-off any optimization
Widget example() {
	Widget volatile a = Widget(1);
	return a;
}