Что я могу сделать с перемещенным объектом?
Стандарт точно определяет, что я могу сделать с объектом после его перемещения? Раньше я думал, что все, что вы можете сделать с перемещенным объектом, это уничтожить его, но этого будет недостаточно.
Например, возьмите шаблон функции swap
как определено в стандартной библиотеке:
template <typename T>
void swap(T& a, T& b)
{
T c = std::move(a); // line 1
a = std::move(b); // line 2: assignment to moved-from object!
b = std::move(c); // line 3: assignment to moved-from object!
}
Очевидно, что должна быть возможность назначить перемещенным объектам, иначе строки 2 и 3 потерпят неудачу. Так что еще я могу сделать с перемещенными объектами? Где именно я могу найти эти детали в стандарте?
(Кстати, почему это T c = std::move(a);
вместо T c(std::move(a));
в строке 1?)
2 ответа
Перемещенные объекты существуют в неопределенном, но действительном состоянии. Это говорит о том, что, хотя объект может быть не в состоянии делать больше, все его функции-члены должны по-прежнему демонстрировать определенное поведение - в том числе operator=
- и все его члены в определенном состоянии - и это все еще требует уничтожения. Стандарт не дает конкретных определений, потому что он будет уникальным для каждого UDT, но вы можете найти спецификации для стандартных типов. Некоторые подобные контейнеры относительно очевидны - они просто перемещают свое содержимое, и пустой контейнер является четко определенным допустимым состоянием. Примитивы не изменяют перемещенный объект.
Примечание: я считаю, что это T c = std::move(a)
так что, если конструктор перемещения (или конструктор копирования, если перемещение не предусмотрено) является явным, функция завершится ошибкой.
17.6.5.15 [lib.types.movedfrom]
Объекты типов, определенных в стандартной библиотеке C++, могут быть перемещены из (12.8). Операции перемещения могут быть явно указаны или неявно сгенерированы. Если не указано иное, такие перемещенные объекты должны быть помещены в допустимое, но неопределенное состояние.
Когда объект находится в неопределенном состоянии, вы можете выполнить любую операцию над объектом, которая не имеет предварительных условий. Если есть операция с предварительными условиями, которую вы хотите выполнить, вы не можете выполнить эту операцию напрямую, потому что не знаете, удовлетворяет ли неопределенное состояние объекта предварительным условиям.
Примеры операций, которые обычно не имеют предварительных условий:
- разрушение
- назначение
- постоянные наблюдатели, такие как
get
,empty
,size
Примеры операций, которые обычно имеют предварительные условия:
- разыменовать
- pop_back
Этот ответ теперь отображается в формате видео здесь: http://www.youtube.com/watch?v=vLinb2fgkHk&t=47m10s