为什么不总是应用 RVO / NRVO?

Lor*_*ins 2 c++

在简要(也可能是过时的和过于简单化)总结返回值优化力学读起来就像这样

一个实现可以在调用者的堆栈帧中创建一个隐藏的对象,并将这个对象的地址传递给函数。然后将函数的返回值复制到隐藏对象中 (...) 大约 1991 年,Walter Bright发明了一种最小化复制的技术,有效地将函数内部的隐藏对象和命名对象替换为用于保存结果的对象 [1 ]

由于这是一个在 SO 上被广泛讨论的话题,我只会链接我找到的最完整的QA

我的问题是,为什么不总是应用返回值优化?更具体地说(基于 中的定义[1]为什么每次函数调用都不总是发生这种替换,因为函数返回类型(因此堆栈上的大小)在编译时总是已知的,这似乎是一个非常有用的功能。

Die*_*ühl 5

显然,当一个左值按值返回时,没有办法不做拷贝。所以,让我们只考虑局部变量。适用于局部变量的一个简单原因是通常不清楚要返回哪个对象。考虑这样的代码:

T f(Args... args) {
    T v1{some_init(args)};
    T v2{some_other(args)};
    bool rc = determine_result(v1, v2);
    return rc? v1: v2;
}
Run Code Online (Sandbox Code Playgroud)

在创建局部变量v1v2创建时,编译器无法判断将返回哪个变量,因此可以就地创建。

另一个原因是复制/移动构建和销毁可能会产生有意的副作用。因此,需要有方法来抑制复制省略。在引入复制省略时,已经有很多 C++ 代码可能依赖于要制作的某些副本,即只有少数情况有资格进行复制省略。