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

时间:2014-12-30 17:20:24

标签: c++

返回值优化机制的简短(可能过时和过度简化)摘要类似于this

  

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

由于它是关于SO的一个主题,我只会链接我找到的最完整的QA

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

2 个答案:

答案 0 :(得分:4)

显然,当按值返回左值时,无法复制。所以,我们只考虑局部变量。应用于局部变量的一个简单原因是,通常不清楚要返回哪个对象。考虑这样的代码:

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

在创建局部变量v1v2时,编译器无法确定哪一个将被返回,因此可以在适当的位置创建它。

另一个原因是复制/移动构造和破坏可能会产生故意的副作用。因此,希望有方法来抑制复制省略。在引入copy-elision时,已经存在很多C ++代码,可能依赖于某些副本,即只有少数情况符合复制elision的条件。

答案 1 :(得分:1)

要求实现执行此操作可能会在某些情况下进行去优化,例如,如果返回值被丢弃。如果您开始添加异常,则开始变得难以证明实现是正确的。

相反,他们采取简单的方法,让实现决定何时进行优化,以及什么时候这样做会适得其反。