Повторно использовать перемещенный контейнер? - PullRequest
73 голосов
/ 07 февраля 2012

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

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 ]

88 голосов
/ 07 февраля 2012

Из раздела 17.3.26 спецификации "действительное, но неопределенное состояние":

состояние объекта, которое не указано, за исключением того, что соблюдаются инварианты объекта и операции над объектом ведут себя так, как указано для его типа [Пример: если объект x типа std::vector<int> находится в допустимом, но неопределенном состоянии, x.empty() может быть вызывается безоговорочно, и x.front() может быть вызвано, только если x.empty() возвращает false. - конец примера]

Следовательно, объект живой. Вы можете выполнить любую операцию, которая не требует предварительного условия (если вы предварительно не проверите предварительное условие).

clear, например, не имеет предварительных условий. И это вернет объект в известное состояние. Так что просто очистите его и используйте как обычно.

10 голосов
/ 07 февраля 2012

Объект, находящийся в допустимом, но неопределенном состоянии , в основном означает, что, хотя точное состояние объекта не гарантируется, оно является действительным, и как такие функции-члены (или функции, не являющиеся членами) гарантированно работать до тех пор, пока они не полагаются на объект, имеющий определенное состояние.

Функция-член clear() не имеет предварительных условий для состояния объекта (конечно, кроме того, что оно действительно) и поэтому может вызываться для объектов, перемещенных из. С другой стороны, например, front() зависит от того, что контейнер не пустой, и поэтому не может быть вызван, поскольку не гарантируется, что он не пустой.

Поэтому и ver2, и ver3 должны быть в порядке.

0 голосов
/ 07 февраля 2012

Я не думаю, что вы можете делать НИЧЕГО с перемещенным объектом (кроме как уничтожить его).

Вы не можете использовать swap вместо этого, чтобы получить все преимущества перемещения, но оставитьконтейнер в известном состоянии?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...