c++ - ¿Por qué un constructor de movimiento requiere un constructor predeterminado para sus miembros?
default-constructor move-constructor (3)
Estaba intentando implementar un constructor de movimiento para una clase sin un constructor de copia. Recibí el error de que faltaba el constructor predeterminado para un miembro de la clase.
Aquí hay un ejemplo trivial para ilustrar esto:
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) {}
};
Tratando de compilar esto, me sale:
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;
^
¿Por qué es esto un error? ¿Alguna forma de evitarlo?
¿Por qué un constructor de movimiento requiere un constructor predeterminado para sus miembros?
El constructor de movimiento que definió por defecto construye un miembro. Si creas miembros por defecto, entonces el constructor por defecto es requerido para esos miembros.
Un constructor (ya sea regular, copiar o mover) por defecto inicializa a los miembros que no están listados en la lista de inicialización de miembros ni tienen una inicialización de miembros por defecto. B::a
no está en la lista de inicialización de miembros del constructor de movimientos (no tiene ninguna lista de inicialización) y no tiene una inicialización de miembros predeterminada.
De alguna manera alrededor de eso?
Más simplemente, use el constructor de movimiento predeterminado:
B(B&&) = default;
El constructor de movimiento por defecto move-construye los miembros.
Un constructor de movimiento en general no tiene que proporcionar inicialización predeterminada. Tu constructor de movimientos lo hace.
Un constructor de movimiento sigue siendo un constructor . Y por lo tanto, debe inicializar todos los subobjetos. Si no proporciona una inicialización explícita, intentará inicializarlos por defecto. Y si no puede hacer eso, obtienes un error.
Así que puedes inicializarlos (quizás moviéndote desde b
), o simplemente usar = default
con tu constructor de movimientos y dejar que el compilador haga su trabajo.
Use la lista de inicializadores del constructor para inicializar el miembro A
Como está escrito, el constructor de movimiento usa, como dice el compilador, el constructor predeterminado para A
B(B&& b) : a(std::move(b.a)) {}