Перемещение оставляет объект в пригодном для использования состоянии?
Скажем, у меня есть два вектора, и я перехожу один к другому, v1 = std::move(v2)
; будут v2
все еще быть в работоспособном состоянии после этого?
3 ответа
Начиная с n3290, 17.6.5.15 Состояние типов библиотек, переведенных из библиотеки [lib.types.movedfrom]
- Объекты типов, определенных в стандартной библиотеке 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() после перемещения.