Может ли конструктор перемещения быть неявным?

Рассмотрим следующий класс:

class A
{
public:
   std::string field_a;
   std::string field_b;
}

Теперь рассмотрим следующую конструкцию копии:

A a1(a2);

Конструкция копии будет надлежащим образом скопировать A, несмотря на отсутствие явного конструктора копирования, поскольку конструкторы копирования для std::string будут вызываться компилятором, сгенерированным неявным конструктором копии.

То, что я хочу знать, так же верно для конструкции перемещения?

EDIT: Тестирование здесь показывает, что:

A a2(std::move(a1));

Фактически это приведет к созданию копии, если только конкретный конструктор перемещения:

A( A && other ) : a(std::move(other.a)) {}

Определяется.

EDIT EDIT Я pinged Stephan T Lavavej и спросил его, почему VC 2012, кажется, не следует, что проект 12.8 состояний относительно неявного создания конструктора движения. Он был достаточно любезен, чтобы объяснить:

Это больше "функция еще не реализована", чем ошибка. VC в настоящее время реализует то, что я называю ссылками rvalue v2.0, где перемещение ctors/assigns никогда не генерируются неявно и никогда не влияют на неявное генерирование копий ctors/assigns. С++ 11 указывает значение rvalue ссылки v3.0, которые являются правилами, которые вы ищете.

Ответ 1

Да, из проекта С++ 11, 12.8:

Если определение класса X явно не объявляет конструктор перемещения, он будет объявлен неявным образом как по умолчанию, если и только если

  • X не имеет объявленного пользователем конструктора копирования,
  • X не имеет объявленного пользователем оператора копирования копий,
  • X не имеет объявленного пользователем оператора назначения перемещения,
  • X не имеет объявленного пользователем деструктора и
  • конструктор перемещения не будет неявно определен как удаленный.

Последнее условие указано более подробно позже:

Неявно объявленный конструктор copy/move является встроенным публичным членом своего класса. По умолчанию конструктор копирования/перемещения для класса X определяется как удаленный (8.4.3), если X имеет:

  • вариантный член с нетривиальным соответствующим конструктором, а X - класс объединения,
  • нестатический элемент данных класса M (или его массив), который не может быть скопирован/перемещен, потому что (13.3), применительно к соответствующему конструктору Ms, приводит к двусмысленности или функция, которая удалена или недоступна из конструктора, установленного по умолчанию,
  • прямой или виртуальный базовый класс B, который нельзя копировать/перемещать, поскольку разрешение перегрузки (13.3), как применяется к соответствующему конструктору Bs, приводит к двусмысленности или функции, которая удалена или недоступный из конструктора, установленного по умолчанию,
  • любой прямой или виртуальный базовый класс или нестатический член данных типа с удаленным деструктором или недоступен из конструктора, установленного по умолчанию,
  • для конструктора копирования, нестатического элемента данных ссылочного типа rvalue или
  • для конструктора перемещения, нестатического элемента данных или прямого или виртуального базового класса с типом, который не имеет конструктора перемещения и не может быть тривиально скопирован.

Проще говоря, конструктор перемещения будет объявлен неявно, если:

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

Ваш класс, очевидно, соответствует этим условиям.

Ответ 2

Компилятор синтезирует конструктор перемещения, если он может, и если нет пользовательского конструктора копирования. Ограничение того, что конструктор перемещения не синтезируется, если есть конструктор копирования, призван избежать нарушения существующего кода. Конечно, все участники должны быть мобильными. Точные правила немного более сложны.