何时移动左值而不是在C++中复制?

Dan*_*tor 7 c++ move move-semantics

鉴于以下内容:

Foo getFoo()
{
    Foo result = doSomeWork();
    return result;
}
Run Code Online (Sandbox Code Playgroud)
  • C++是否保证result将被移动而不是复制?换句话说,写作是return std::move(result)多余的?

  • 是否有任何(其他)情况,标准指定在没有显式std::move强制转换的情况下,左值将被静默移动而不是复制?

笔记:

  • 假设Foo是可移动构造的.

  • 无视复制/移动省略,这可能另外适用.

Col*_*mbo 5

  1. 尽管可以忽略此举,但可以。如果移动构造函数可用,则复制永远不会发生。为了清楚起见,我将再次引用该段。[class.copy] / 32:

    当满足复制/移动操作的省略标准,但不满足异常声明的条件并且要复制的对象由左值指定时,或者return 语句中的表达式为(可能带有括号)id-expression在最内层的封闭函数或lambda-expression的主体或参数声明子句声明了具有自动存储期限的对象 , 过载分辨率选择首先执行用于复制的构造为如果对象是由一个rvalue指定。如果第一个重载解析失败或没有执行,或者如果所选构造函数的第一个参数的类型不是对该对象类型的右值引用(可能是cv限定),则再次执行重载解析,将对象视为左值。[ 注意:无论是否出现复制省略,都必须执行此两阶段重载解决方案。如果不执行省略操作,它将确定要调用的构造函数,并且即使取消了调用,所选的构造函数也必须可访问。—尾注 ]

    应用std::move并不是多余的,但实际上阻止了复制省略的执行,[class.copy] / 31:

    return当表达式是非易失性自动对象 [..] 的名称时,在具有类返回类型的函数的语句中

  2. 是的,有一种情况-我再次假设您的意思是,如果不执行复制省略,则将执行一次移动(如果左值被移动,复制省略必须适用,sa)。
    考虑一下:

    A a;
    throw a;
    
    Run Code Online (Sandbox Code Playgroud)

    符合条件:

    —在throw-expression中,当操作数是非易失性自动对象(函数或catch子句参数除外)的名称时,其范围不会超出最里面的try-block的末尾(如果存在)一种),可以通过将自动对象直接构造到异常对象中来省略从操作数到异常对象(15.1)的复制/移动操作

    演示
    这是唯一的一个左值被移动而不是被复制的情况。复制省略的其他两种情况仅包括未绑定到引用的临时项(因此必须由prvalues指定)和例外声明thing,这在这里没有意义,因为它涵盖了我们未看到的例外对象。