为什么移动构造函数需要使用“右值引用”?

时间:2013-08-09 13:35:18

标签: c++ c++11 constructor move-constructor

例如,以下移动构造函数在没有&&(右值引用)的情况下工作:

Obj::Obj(Obj& obj) : elem { obj.elem }, data(obj.data) {

    obj.elem = nullptr;
    obj.data = 0;

}

我真的不明白为什么有必要......

2 个答案:

答案 0 :(得分:14)

Rvalue引用参数将拒绝绑定到非右值引用。由于这种限制,move操作只会在以后永远不能在代码中显式引用被移动的对象时发生(因为它是临时被丢弃的,或者是返回的局部变量),或者因为来电者明确地move了。

要查看为何需要这样做,您可以查看auto_ptr的历史记录,或者您可以阅读此示例,该示例使用您的Obj类型:

int main() {
  Obj a;
  Obj b = a; // oops!  You just *moved* a into b!
}

使用正确的move构造函数,只有在右侧是一个将以编译器可以检测到的方式立即丢弃的值或者调用move时才会调用它。

最重要的是,&引用拒绝绑定到临时对象 - 临时只能绑定到const&&&

答案 1 :(得分:12)

您的示例无法绑定到临时,因此这些不起作用:

Obj makeObj() { return Obj(); }

Obj o1(Obj());     // Error
Obj o2(makeObj()); // Error

此外,它可以很容易地破坏事物,因为你本质上有一个复制构造函数,可以从正在复制的对象中窃取状态:

Obj o1;
Obj o2{o1}; // o1 is modified