Ответ 1
Используйте список инициализаторов конструктора для инициализации члена A
. Как написано, конструктор перемещения использует, как компилятор, конструктор по умолчанию для A
.
B(B&& b) : a(std::move(b.a)) {}
Я пытался реализовать конструктор перемещения для класса без конструктора копирования. У меня возникла ошибка, когда конструктор по умолчанию для члена класса отсутствовал.
Вот тривиальный пример, иллюстрирующий это:
struct A {
public:
A() = delete;
A(A const&) = delete;
A(A &&a) {}
};
struct B {
A a;
B() = delete;
B(B const&) = delete;
B(B &&b) {}
};
Пытаясь скомпилировать это, я получаю:
move_without_default.cc: In constructor ‘B::B(B&&)’:
move_without_default.cc:15:11: error: use of deleted function ‘A::A()’
B(B &&b) {}
^
move_without_default.cc:6:2: note: declared here
A() = delete;
^
Почему это ошибка? В любом случае?
Используйте список инициализаторов конструктора для инициализации члена A
. Как написано, конструктор перемещения использует, как компилятор, конструктор по умолчанию для A
.
B(B&& b) : a(std::move(b.a)) {}
Почему конструктор перемещения требует конструктора по умолчанию для своих членов?
Конструктор перемещения , который вы определили по умолчанию, создает элемент. Если вы по умолчанию строите какие-либо элементы, для этих членов требуется конструктор по умолчанию.
Конструктор (регулярный, копирующий или перемещаемый) по умолчанию инициализирует члены, которые не указаны в списке инициализации членов, или не имеют инициализацию члена по умолчанию. B::a
не входит в список инициализации члена конструктора перемещения (он вообще не имеет списка инициализации) и не имеет инициализации члена по умолчанию.
В любом случае?
Проще говоря, используйте конструктор перемещения по умолчанию:
B(B&&) = default;
Конструктор перемещения по умолчанию перемещает-конструирует элементы.
Конструктор перемещения вообще не должен обеспечивать инициализацию по умолчанию. Конструктор перемещения делает.
Конструктор перемещения по-прежнему является конструктором. И поэтому он должен инициализировать все подобъекты. Если вы не предоставите явную инициализацию, то он попытается инициализировать их по умолчанию. И если он не может этого сделать, вы получите сообщение об ошибке.
Итак, вы можете либо инициализировать их (возможно, переместившись с b
), либо просто использовать = default
с вашим конструктором перемещения и позволить компилятору выполнять эту работу.