Почему конструктор перемещения требует конструктора по умолчанию для своих членов?

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

Вот тривиальный пример, иллюстрирующий это:

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;
  ^

Почему это ошибка? Как-нибудь обойти это?


person ynimous    schedule 02.09.2016    source источник
comment
заменить {} на = default;   -  person cpplearner    schedule 02.09.2016
comment
Потому что конструктор по умолчанию A удален, но B использует его.   -  person tkausl    schedule 02.09.2016
comment
Пустой конструктор перемещения не будет автоматически пытаться выполнить перемещение по элементам. Ваш конструктор перемещения пытается построить по умолчанию a, а не построить его.   -  person user2357112 supports Monica    schedule 02.09.2016
comment
Гм, удаление конструкторов по умолчанию и копирования A и отсутствие реализации каких-либо других конструкторов, кроме конструктора перемещения, не означает ли это, что объект A никогда не может быть создан до того, как его можно будет переместить в другой объект A? Или такие вещи, как инициализация фигурной скобки, обходят это?   -  person Remy Lebeau    schedule 02.09.2016


Ответы (3)


Используйте список инициализаторов конструктора для инициализации члена A. Как написано, конструктор перемещения использует, как говорит компилятор, конструктор по умолчанию для A.

B(B&& b) : a(std::move(b.a)) {}
person Pete Becker    schedule 02.09.2016

Почему конструктор перемещения требует конструктора по умолчанию для своих членов?

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

Конструктор (будь то обычный, копирование или перемещение) по умолчанию инициализирует элементы, которые не перечислены в списке инициализации элементов и не имеют инициализации элементов по умолчанию. B::a отсутствует в списке инициализации членов конструктора перемещения (у него вообще нет списка инициализации) и у него нет инициализации членов по умолчанию.

Как-нибудь обойти это?

Проще всего использовать конструктор перемещения по умолчанию:

B(B&&) = default;

Конструктор перемещения по умолчанию перемещает элементы.

person eerorika    schedule 02.09.2016

Конструктор перемещения обычно не должен обеспечивать инициализацию по умолчанию. Ваш конструктор перемещения делает это.

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

Таким образом, вы можете либо инициализировать их (возможно, переходя от b), либо просто использовать = default с вашим конструктором перемещения и позволить компилятору выполнить свою работу.

person Nicol Bolas    schedule 02.09.2016