在多个return语句的情况下,返回`std :: move`是否合理?

lef*_*out 22 c++ move-semantics return-value-optimization c++11

我知道回归通常不是一个好主意std::move,即

bigObject foo() { bigObject result; /*...*/ return std::move(result); }
Run Code Online (Sandbox Code Playgroud)

而不是简单的

bigObject foo() { bigObject result; /*...*/ return result; }
Run Code Online (Sandbox Code Playgroud)

因为它妨碍了返回值优化.但是在具有多个不同回报的函数的情况下,特别是类似的东西

class bar {
  bigObject fixed_ret;
  bool use_fixed_ret;
  void prepare_object(bigObject&);
 public:
  bigObject foo() {
    if(use_fixed_ret)
      return fixed_ret;
     else{
      bigObject result;
      prepare_object(result);
      return result;
    }
  }
};
Run Code Online (Sandbox Code Playgroud)

我认为在这样的函数中,正常的返回值优化是不可能的,所以投入是一个好主意

      return std::move(result);
Run Code Online (Sandbox Code Playgroud)

在这里,或者我应该做什么(IMO丑陋,但这是有争议的)

  bigObject foo() {
    bigObject result;
    if(use_fixed_ret)
      result = fixed_ret;
     else{
      prepare_object(result);
    }
    return result;
  }
Run Code Online (Sandbox Code Playgroud)

Xeo*_*Xeo 33

对于局部变量,大多数情况下std::movereturn语句中不需要它们,因为语言实际上要求自动发生这种情况:

§12.8 [class.copy] p32

当满足或将满足复制操作的省略标准时,除了源对象是函数参数这一事实,并且要复制的对象由左值指定,重载决策选择复制的构造函数是首先执行,好像对象是由右值指定的.如果重载决策失败,或者所选构造函数的第一个参数的类型不是对象类型的rvalue引用(可能是cv-qualified),则再次执行重载决策,将对象视为左值.[ 注意:无论是否发生复制省略,都必须执行此两阶段重载决策.如果未执行elision,它将确定要调用的构造函数,并且即使调用被省略,也必须可以访问所选的构造函数.- 尾注 ]


†复制省略在可以应用的地方非常有限(§12.8/31).一个这样的限制是源对象的类型必须与处理return语句时函数的cv-nonqualified返回类型相同.它也不适用于即将超出范围的局部变量的子对象.

  • 这是您的标准参考. (2认同)
  • @leftaroundabout:它基本上说,"如果对象是本地的,并且是由返回值,首先尝试将其返回作为右值(如'的std :: move`会做),如果没有找到一个举动构造函数,尝试.同样但这次作为左值. (2认同)