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

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

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

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