Повторное использование перемещенного контейнера?
Каков правильный способ повторного использования перемещенного контейнера?
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);
Из того, что я прочитал в стандартном черновике С++ 0x; ver3 кажется правильным, поскольку объект после перемещения находится в
"Если не указано иное, такие перемещенные объекты должны быть размещены в действительном, но неуказанном состоянии."
Я никогда не встречал ни одного экземпляра, где он "указан иначе".
Хотя я нахожу ver3 немного круговым и будет очень предпочтительным ver1, хотя vec3 может позволить некоторую дополнительную оптимизацию, но, с другой стороны, может легко привести к ошибкам.
Правильно ли мое предположение?
Ответы
Ответ 1
Из раздела 17.3.26 спецификации "действительное, но неуказанное состояние":
состояние объекта, которое не указано, за исключением того, что инварианты объектов выполнены, и операции над объектом ведут себя так, как указано для его типа [Пример: если объект x
типа std::vector<int>
находится в действительном, но неуказанном состоянии, x.empty()
может быть вызываемый безоговорочно, и x.front()
можно вызывать, только если x.empty()
возвращает false. -end пример]
Следовательно, объект жив. Вы можете выполнить любую операцию, которая не требует предварительного условия (если только вы не проверите предварительное условие).
clear
, например, не имеет предварительных условий. И он вернет объект в известное состояние. Поэтому просто очистите его и используйте как обычно.
Ответ 2
Объект, находящийся в действительном, но undefined состоянии в основном означает, что, хотя точное состояние объекта не гарантируется, оно действительно и как таковые функции-члены (или не-членские функции) гарантированы работать до тех пор, пока они не полагаются на объект, имеющий определенное состояние.
Элемент-член clear()
не имеет никаких предварительных условий для состояния объекта (иначе он действителен, конечно) и поэтому может быть вызван при перемещении из объектов. С другой стороны, например, front()
зависит от того, что контейнер не пуст, и поэтому его нельзя вызывать, поскольку он не гарантированно не пуст.
Поэтому оба ver2 и ver3 должны быть хорошими.
Ответ 3
Я не думаю, что вы можете делать НИЧЕГО с перемещенным объектом (кроме его уничтожения).
Не можете ли вы использовать swap
, чтобы получить все преимущества перемещения, но оставить контейнер в известном состоянии?