Перемещение оставляет объект в пригодном для использования состоянии?

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

3 ответа

Решение

Начиная с n3290, 17.6.5.15 Состояние типов библиотек, переведенных из библиотеки [lib.types.movedfrom]

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

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

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

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

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

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

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

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

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

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

Другие вопросы по тегам