Повторно использовать перемещенный контейнер?
Как правильно использовать перемещенный контейнер?
std::vector<int> container;
container.push_back(1);
auto container2 = std::move(container);
// ver1: Do nothing
//container2.clear(); // ver2: "Reset"
container = std::vector<int>() // ver3: Reinitialize
container.push_back(2);
assert(container.size() == 1 && container.front() == 2);
Из того, что я прочитал в черновике стандарта C++0x; ver3, кажется, правильный путь, так как объект после перемещения находится в
"Если не указано иное, такие перемещенные объекты должны быть помещены в действительное, но неопределенное состояние".
Я никогда не находил ни одного экземпляра, где бы это "не указывалось иначе".
Хотя я считаю ver3 немного окольным и предпочел бы ver1, хотя vec3 может позволить некоторую дополнительную оптимизацию, но с другой стороны может легко привести к ошибкам.
Правильно ли мое предположение?
3 ответа
Из раздела 17.3.26 спецификации "действительное, но неопределенное состояние":
состояние объекта, которое не указано, за исключением того, что соблюдаются инварианты объекта и операции над объектом ведут себя так, как указано для его типа [Пример: если объект
x
типаstd::vector<int>
находится в действительном, но неопределенном состоянии,x.empty()
можно назвать безоговорочно, иx.front()
можно назвать только еслиx.empty()
возвращает ложь - конец примера]
Поэтому объект живой. Вы можете выполнить любую операцию, которая не требует предварительного условия (если вы предварительно не проверите предварительное условие).
clear
Например, не имеет никаких предпосылок. И он вернет объект в известное состояние. Так что просто очистите его и используйте как обычно.
Объект, находящийся в допустимом, но неопределенном состоянии, в основном означает, что, хотя точное состояние объекта не гарантируется, оно является действительным, и, таким образом, такие функции-члены (или не-функции-члены) гарантированно будут работать до тех пор, пока они не полагаются на объект, имеющий определенное состояние.
clear()
memberfunction не имеет предварительных условий для состояния объекта (кроме, конечно, он действителен) и поэтому может быть вызван при перемещении из объектов. С другой стороны, например front()
зависит от того, является ли контейнер не пустым, и поэтому не может быть вызван, поскольку не гарантируется, что он не пуст.
Поэтому и ver2, и ver3 должны быть в порядке.
Я не думаю, что вы можете делать НИЧЕГО с перемещенным объектом (кроме как уничтожить его).
Вы не можете использовать swap
вместо этого, чтобы получить все преимущества перемещения, но оставить контейнер в известном состоянии?