Что я могу сделать с перемещенным объектом?

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

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

Ответ 1

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

Боковое примечание: я считаю, что это T c = std::move(a), так что если конструктор перемещения (или конструктор копирования, если не задан ход) явно явствует, функция будет терпеть неудачу.

Ответ 2

17.6.5.15 [lib.types.movedfrom]

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

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

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

  • разрушение
  • Назначение
  • const наблюдатели, такие как get, empty, size

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

  • разыменовать
  • pop_back

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