所以我被这几次烧伤了。有什么区别:
Movable&& object = std::move(another_movable);
和此:
Movable object = std::move(another_movable);
似乎两者应该同等地工作,但我总是得到第二个例子的莫名其妙的行为(对象的属性改变)。这是为什么?
答案 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初始化仍然会复制整个对象,但之后它确保当旧对象被销毁时,它上面的数据将保留,这应该通过更改旧对象的指针来完成!编译器实际上并没有做任何事情,所使用的程序和标题必须确保预期的事情已经完成!