在多个return语句的情况下,返回时带有“std::move”明智



我知道返回std::move(即)通常不是一个好主意

bigObject foo() { bigObject result; /*...*/ return std::move(result); }

而不是简单的

bigObject foo() { bigObject result; /*...*/ return result; }

因为它妨碍了返回值优化。但是,在一个函数有多个不同的返回的情况下,特别是像这样的函数

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;
    }
  }
};

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

      return std::move(result);

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

  bigObject foo() {
    bigObject result;
    if(use_fixed_ret)
      result = fixed_ret;
     else{
      prepare_object(result);
    }
    return result;
  }

对于局部变量,大多数时候不需要在return语句中std::move它们,因为语言实际上要求自动发生:

§12.8 [class.copy] p32

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


†拷贝省略在应用方面受到很大限制(§12.8/31)。其中一个限制是,在处理返回语句时,源对象的类型必须与函数的cv非限定返回类型相同。它也不适用于即将超出范围的局部变量的子对象。

最新更新