Что я могу сделать с перемещенным объектом? - PullRequest
130 голосов
/ 11 августа 2011

Стандарт точно определяет, что я могу делать с объектом после его перемещения?Раньше я думал, что все, что вы можете сделать с перемещенным объектом - это уничтожить его, но этого будет недостаточно.

Например, возьмите шаблон функции 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 ]

105 голосов
/ 11 августа 2011

17.6.5.15 [lib.types.movedfrom]

Объекты типов, определенных в стандартной библиотеке C ++, можно перемещать из (12,8). Операции перемещения могут быть указаны явно или неявно генерироваться. Если не указано иное, такие перемещенные объекты должны находиться в действительном, но не указанном состоянии.

Когда объект находится в неопределенном состоянии, вы можете выполнить любую операцию над объектом, которая не имеет предварительных условий. Если есть операция с предварительными условиями, которую вы хотите выполнить, вы не можете выполнить эту операцию напрямую, потому что не знаете, удовлетворяет ли неопределенное состояние объекта предварительным условиям.

Примеры операций, которые обычно не имеют предварительных условий:

  • разрушения
  • Назначение
  • постоянные наблюдатели, такие как get, empty, size

Примеры операций, которые обычно имеют предварительные условия:

  • разыменования
  • pop_back

Этот ответ теперь отображается в формате видео здесь: http://www.youtube.com/watch?v=vLinb2fgkHk&t=47m10s

50 голосов
/ 11 августа 2011

Перемещенные объекты существуют в неопределенном, но действительном состоянии. Это говорит о том, что, хотя объект больше не способен на многое, все его функции-члены должны по-прежнему демонстрировать определенное поведение & mdash; в том числе operator= & mdash; и все его члены в определенном состоянии - и это все еще требует разрушения. Стандарт не дает конкретных определений, потому что он будет уникальным для каждого UDT, но вы можете найти спецификации для стандартных типов. Некоторые подобные контейнеры относительно очевидны & mdash; они просто перемещают свое содержимое, и пустой контейнер является четко определенным допустимым состоянием. Примитивы не изменяют перемещенный объект.

Примечание: я полагаю, что это T c = std::move(a), поэтому, если конструктор перемещения (или конструктор копирования, если перемещение не указано) является явным, функция завершится ошибкой.

...