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

时间:2014-12-29 20:26:46

标签: c++ move move-semantics

鉴于以下内容:

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

  • 是否有任何(其他)情况,标准指定在没有明确的std::move演员表的情况下静默移动左值而不是复制左眼?

备注:

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

  • 无视复制/移动省略,可另外申请。

2 个答案:

答案 0 :(得分:4)

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

      

    满足复制/移动操作的省略标准时,但是   不是异常声明和要复制的对象   由左值指定,或在return中表达时   statement是一个(可能带有括号的) id-expression ,用于命名   具有在体内声明的自动存储持续时间的对象   首先执行最内层封闭函数的 parameter-declaration-clause lambda-expression 重载决策以选择复制的构造函数,就好像该对象由一个   右值即可。如果第一个重载决议失败或没有   执行,或者如果所选的第一个参数的类型   构造函数不是对象类型的右值引用(可能   cv-qualified),重新执行重载决策,考虑到   对象作为左值。 [注意:这个两阶段的重载决议必须   无论是否会发生复制,都会执行。它   如果没有执行elision,则确定要调用的构造函数,   并且即使呼叫是必须的,也必须可以访问所选的构造函数   省略。 - 结束记录]

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

      

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

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

    A a;
    throw a;
    

    符合标准:

      

    - 在 throw-expression 中,当操作数是a的名称时   非易失性自动对象(函数或catch子句除外)   参数)其范围不超出最内层的末端   封闭try-block(如果有的话),复制/移动操作   异常对象(15.1)的操作数可以省略   将自动对象直接构造到异常对象

    Demo
    这是移动左值而不是复制左手的唯一其他情况;复制省略的另外两种情况仅包括未绑定到引用的临时(因此必须由prvalues指定)和异常声明的东西,这在这里是无趣的,因为它涵盖了我们看不到的异常对象。

答案 1 :(得分:0)

我认为这是一个返回值优化的案例。 http://en.wikipedia.org/wiki/Return_value_optimization 编译器根本不会复制或移动对象,而是识别它。 所以,不,我不会写return std::move(result)它甚至可能使编译器无法优化。