RVO 何时保证适用/确实适用于 C++20 编译器

When is RVO garanteed to apply / does apply with C++20 compilers

C++ 核心指南指出

F.20: For “out” output values, prefer return values to output parameters

但随后出现以下异常:

struct Package {      // exceptional case: expensive-to-move object
    char header[16];
    char load[2024 - 16];
};

Package fill();       // Bad: large return value
void fill(Package&);  // OK

这不应该是 return 价值优化开始的情况吗?在这种情况下是否阻止了 RVO?或者仍然不如通过引用传递有效?还是某些编译器无法做到这一点?

更一般地说,我什么时候应该依赖 编译器优化 return 值与传递引用技术一样有效?

Or still not as efficient as passing by reference ?

如果应用 RVO,那么 return 一个值与使用输出参考一样有效。

Is RVO prevented in this case?

没有。 “大”不会阻止对象被 RVO。

When is RVO garanteed to apply / does apply with C++20 compilers

不适用的情况:

... 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.

所以,是否保证copy-elision取决于函数的实现。

指南确实无法解释为什么应该遵循建议。

请注意异常显示:

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).

例外中突出显示的建议对我来说更有意义。它清楚地表明对象太大而无法堆栈,从而减少堆栈溢出的机会。

"Plain" RVO(即,返回纯右值或 "temporary" 在普通话中)在 C++17 中得到保证,甚至在此之前就得到了很好的支持。

NRVO(即返回一个局部变量)可能很挑剔并且不能保证,如果它没有执行,那么你会得到一个移动。如果您的搬家费用昂贵,您可能希望避免这种情况。

在示例中,fill 很有可能需要使用后者。