When is RVO garanteed to apply / does apply with C++20 compilers
Or still not as efficient as passing by reference ?
If RVO applies, then it is equally efficient to return a value, as it is to use an output reference.
Is RVO prevented in this case?
No. Being "big" does not prevent the object from being RVO'd.
When is RVO garanteed to apply / does apply with C++20 compilers
A case where it does not apply:
... A return statement can involve an invocation of a constructor to perform a copy or move of the operand if it is not a prvalue or if its type differs from the return type of the function.
So, it depends on the implementation of the function whether copy-elision is guaranteed.
The guidelines indeed fail to explain why the recommendation should be followed.
Note that the exception says:
Exceptions
If a type is expensive to move (e.g.,
array<BigPOD>
), consider allocating it on the free store and return a handle (e.g., unique_ptr), or passing it in a reference to non-const target object to fill (to be used as an out-parameter).
The highlighted suggestion in the exception makes more sense to me. It makes it clear that the object is too big for stack, and thus reduces the chance stack overflows.
"Plain" RVO (i.e., returning a prvalue or "temporary" in common parlance) is guaranteed in C++17 and well-supported even before that.
NRVO (i.e., returning a local variable) can be finicky and is not guaranteed, and if it's not performed then you get a move instead. If your move is expensive, you may want to avoid that.
In the example, there's a decent chance that fill
needs to use the latter.