2014-08-28 2 views
4

Так что я был сожжен этим пару раз. В чем разница между этим:Что происходит, когда вы переходите на ссылку rvalue?

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

и это:

Movable object = std::move(another_movable); 

Похоже, оба должны работать одинаково, но я всегда получаю необъяснимое поведение (свойства меняющегося объекта) со вторым примером. Почему это?

+0

Один создает ссылку, другой создает экземпляр объекта. – juanchopanza

+0

Итак, первый вызывает конструктор перемещения, а второй вызов переводит назначение? – sircodesalot

+0

Нет, первое не вызывает ничего, как ссылка lvalue, а вторая вызывает конструктор перемещения. – chris

ответ

6

Может быть, сравнивая его с именующим-справочной версией может помочь:

Object& object = another_object; 

Object object = another_object; 

Первой ссылка на Lvalue, поэтому никаких конструкторов не называются. Это просто относится к к объекту с именем another_object, как указатель. Object object создает совершенно новый объект, поэтому конструкторы будут называться (не предполагая copy-elision).

Теперь ссылки rvalue одинаковы, но они предназначены исключительно для rvalues. Они теперь ссылаются на на rvalue, из которого он инициализируется.

+0

А, это совершенно ясно, спасибо! – sircodesalot

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

Это делает еще одну ссылку на тот же объект, another_movable.

Movable object = std::move(another_movable); 

Это делает новый объект инициализирован из RValue из another_movable.

0

как уже было сказано, сначала копирование ссылки. как и для всех типов указателей, вы действительно не должны иметь тип возврата, являющийся значением rvalue, если он не находится в куче.

однако, второй немного сложнее, чем просто инициализация rvalue. рассмотреть следующие вопросы:

Moveable object = another_moveable; 

или

Moveable object = function_returning_another_moveable(); 

, казалось бы, последняя инициализация от истинной, не-литой RValue. но см. http://en.cppreference.com/w/cpp/language/copy_elision

, а прежний фактически зависит от того, какие конструкторы перемещаются.

Что касается неожиданного поведения, это, скорее всего, из-за наследования-потери, так сказать. т. е. если another_moveable является только производным от Moveable, Moveable будет использовать инициализацию rvalue для родителя Moveable только для another_moveable, и любые данные, полученные производным объектом, теперь теряются.

только для акцента: Перемещаемый с инициализацией rvalue не означает, что другой объект просто получает новую ссылку, инициализация rvalue предназначена для хранения данных, хранящихся в куче, где они были, с указанием только указателей и ссылок в новом объекты копируются из старого. Инициализация rvalue все еще копирует весь объект, но впоследствии он гарантирует, что когда старый объект будет уничтожен, его данные в куче будут оставаться, и это должно быть сделано путем изменения указателей старого объекта! компилятор на самом деле ничего не делает, программа и используемые заголовки должны следить за тем, чтобы все было сделано!

Смежные вопросы