Перемещение оставляет объект в пригодном для использования состоянии? - PullRequest
14 голосов
/ 28 октября 2011

Скажем, у меня есть два вектора, и я перехожу один к другому v1 = std::move(v2);v2 все еще будет в пригодном для использования состоянии после этого?

Ответы [ 3 ]

23 голосов
/ 28 октября 2011

Из n3290, 17.6.5.15 Состояние перемещенных из библиотеки типов библиотек [lib.types.movedfrom]

  1. Объекты типов, определенных в стандартной библиотеке C ++, можно перемещать из (12.8).Операции перемещения могут быть явно указаны или неявно сгенерированы.Если не указано иное, такие перемещенные объекты должны быть помещены в действительное, но неопределенное состояние.

Поскольку состояние действительно, это означает, что вы можете безопасно работать с v2 (например,присвоение ему, которое вернуло бы его в известное состояние).Однако, поскольку оно не указано, это означает, что вы не можете, например, полагаться на какое-либо конкретное значение для v2.empty(), пока оно находится в этом состоянии (но его вызов не приведет к сбою программы).

Обратите внимание, что этоСемантика аксиомы перемещения («перемещенные объекты остаются в допустимом, но неопределенном состоянии») - это то, к чему должен стремиться весь код (большую часть времени), а не только компоненты стандартной библиотеки.Так же, как семантика конструкторов копирования должна делать копию, но не применяется к.

7 голосов
/ 28 октября 2011

Нет, он оставлен в неопределенном состоянии.

Выдержка из open-std-org статья -

.. move () дает своей цели значение своего аргумента, но не обязан сохранять значение своего источника . Таким образом, можно ожидать, что для вектора move () оставит свой аргумент в качестве вектора нулевой емкости, чтобы избежать необходимости копировать все элементы. Другими словами, движение - потенциально разрушительное чтение.

0 голосов
/ 06 февраля 2018

Если вы хотите, чтобы использовал v2 после перемещения, вы захотите сделать что-то вроде:

v1 = std::move(v2);
v2.clear();

На этом этапе v1 будет иметь исходное содержимое v2 и v2будет в четко определенном пустом состоянии.Это работает на всех контейнерах STL (и, в данном случае, на строках), и если вы реализуете свои собственные классы, которые поддерживают семантику перемещения, вы, вероятно, захотите сделать что-то подобное.

Если ваша конкретная реализация STL на самом деле оставляет объект в пустом состоянии, то второй метод clear () по сути будет неактивным.На самом деле, если это так, компилятору было бы законно оптимизировать удаление clear () после перемещения.

...