当你转向不是左值参考时会发生什么?

时间:2014-08-28 14:06:38

标签: c++ c++11

所以我被这几次烧伤了。有什么区别:

 Movable&& object = std::move(another_movable);

和此:

 Movable object = std::move(another_movable);

似乎两者应该同等地工作,但我总是得到第二个例子的莫名其妙的行为(对象的属性改变)。这是为什么?

3 个答案:

答案 0 :(得分:6)

将它与左值参考版本进行比较可能有所帮助:

Object& object = another_object;

Object object  = another_object;

第一个是对左值的引用,因此不会调用构造函数。它只是引用到名为another_object的对象,就像一个指针。 Object object创建一个全新的对象,因此将调用构造函数(不假设copy-elision)。

现在rvalue-references是相同的,但它们专门为rvalues定制。他们现在引用到初始化它的右值。

答案 1 :(得分:5)

Movable&& object = std::move(another_movable);

这使得对another_movable的同一对象的另一个引用。

Movable object = std::move(another_movable);

这使得一个新对象从another_movable的右值初始化。

答案 2 :(得分:0)

如前所述,首先是复制引用。与所有指针类型一样,除非它在堆上,否则你不应该将返回类型作为右值。

然而,第二个比仅仅是一个rvalue初始化要复杂一点。考虑:

Moveable object = another_moveable;

Moveable object = function_returning_another_moveable();
似乎后者是从真正的非铸造rvalue初始化。但请参阅http://en.cppreference.com/w/cpp/language/copy_elision

前者实际上取决于Moveable的构造函数。

对于意外行为,这很可能是因为继承丢失,所以说。即如果another_moveable仅从Moveable派生,则Moveable将仅对another_moveable的Moveable parent使用rvalue初始化,并且派生对象的所有数据现在都将丢失。

只是为了强调:具有rvalue初始化的可移动并不意味着另一个对象只是获得一个新的引用,rvalue初始化用于存储在堆上的数据保持原样,只有指针和引用从旧的复制旧对象。 rvalue初始化仍然会复制整个对象,但之后它确保当旧对象被销毁时,它上面的数据将保留,这应该通过更改旧对象的指针来完成!编译器实际上并没有做任何事情,所使用的程序和标题必须确保预期的事情已经完成!