RVO(返回值优化)是否适用于所有对象?

mas*_*oud 47 c++ optimization gcc

RVO(返回值优化)是否保证适用于C++编译器(特别是GCC)中的所有对象和情境?

如果答案是"否",那么对类/对象进行优化的条件是什么?如何强制或鼓励编译器对特定的返回值执行RVO?

Dav*_*eas 45

始终可以应用返回值优化,不能普遍应用的是命名返回值优化.基本上,为了进行优化,编译器必须知道在构造对象的位置将返回什么对象.

在RVO(返回临时的情况)的情况下,该条件得到满足:对象在return语句中构造,并且返回它.

对于NRVO,您必须分析代码以了解编译器是否可以知道该信息.如果对函数的分析很简单,那么编译器可能会对它进行优化(例如,不包含条件的单个return语句;同一个对象的多个return语句;多个返回语句,如T f() { if (condition) { T r; return r; } else { T r2; return r2; } }编译器知道rr2 将会被退回...)

请注意,您只能在简单情况下假设优化,具体而言,维基百科中的示例实际上可以通过足够聪明的编译器进行优化:

std::string f( bool x ) {
   std::string a("a"), b("b");
   if ( x ) return a; 
   else return b;
}
Run Code Online (Sandbox Code Playgroud)

可以由编译器重写为:

std::string f( bool x ) {
   if ( x ) {
      std::string a("a"), b("b");
      return a;
   } else {
      std::string a("a"), b("b");
      return b;
   }
}
Run Code Online (Sandbox Code Playgroud)

并且编译器此时可以知道在第一个分支a中构造代替返回的对象,并且在第二个分支中同样适用b.但我不指望这一点.如果代码很复杂,则假设编译器无法生成优化.

编辑:有一个我没有明确提到的情况,不允许编译器(在大多数情况下,即使它被允许,也不可能这样做)来优化从函数的参数到return语句的副本:

T f( T value ) { return value; } // Cannot be optimized away --but can be converted into
                                 // a move operation if available.
Run Code Online (Sandbox Code Playgroud)

  • 请注意,RVO/NRVO仅在返回*临时对象*时适用,即在复制后通常会被破坏的对象.例如,从成员函数返回成员变量时,必须发生副本.对于一些人来说,这似乎是显而易见的,但我不得不向多个人解释这一点,因为他们只是了解RVO. (3认同)

Lig*_*ica 5

是否保证gcc编译器中所有对象的RVO(返回值优化)?

没有任何优化得到保证(尽管RVO相当可靠,但确实存在一些将其抛弃的情况).

如果答案是"否",那么这个类/对象的优化条件是什么?

一个非常故意从您身上抽象出来的实现细节.

请不要知道也不关心这个.

  • 你的最后一点是Javaish评论的一点点.;)知道它是没有害处的,它可能是特定于实现的,但如果这样倾向 - 为什么不呢?但是,至于关怀,只有剖析突出它... (6认同)
  • RVO**可以**始终应用,NRVO是有时无法应用的. (2认同)