编译器何时不能使用RVO或NRVO?

6

当编译器无法使用RVONRVO时,移动语义可能很有用。但在什么情况下编译器无法使用这些功能呢?


2个回答

5
答案是这取决于编译器和情况。例如,控制流分支可能会使优化器混淆。维基百科(Wikipedia)给出了一个例子:
#include <string>
std::string f(bool cond = false) {
  std::string first("first");
  std::string second("second");
  // the function may return one of two named objects
  // depending on its argument. RVO might not be applied
  return cond ? first : second;
}

int main() {
  std::string result = f();
}

3

其实问题不在于编译器能否使用返回值优化(RVO),而是它是否能避免进行复制构造。

请看:

struct Blah
{
    int x;
    Blah( int const _x ): x( _x ) { cout << "Hum de dum " << x << endl; }
};

Blah foo()
{
    Blah const a( 1 );
    if( fermatWasRight() ) { return Blah( 2 ); }
    return a;
}

在这里正确获取副作用(构造函数的输出),乍一看与直接在调用方提供的存储中构建 a 不太兼容。但是如果编译器足够聪明,则它可以注意到销毁此对象是一个空操作。并且更普遍地说,对于任何特定情况,如果编译器足够聪明,则即使我们如何狡猾地设计代码,它也可能设法避免复制操作。
我不确定正式情况,但是上述情况,如果对象的有效负载更大,以至于复制会更昂贵,则是移动语义有所帮助的一种情况,因此优化将得到保证,无论编译器是否聪明(或不聪明)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接