Повторное использование перемещенного контейнера?

Каков правильный способ повторного использования перемещенного контейнера?

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, чтобы получить все преимущества перемещения, но оставить контейнер в известном состоянии?