I was trying to implement a move constructor for a class without a copy constructor. I got an error that the default constructor for a member of the class was missing.
Here's a trivial example to illustrate this:
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) {}
};
Trying to compile this, I get:
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;
^
Why is this an error? Any way around it?
What is the significance of the default constructor? They are used to create objects, which do not have any specific initial value. Is a default constructor automatically provided? If no constructors are explicitly declared in the class, a default constructor is provided automatically by the compiler.
For non-union class types (class and struct), the move constructor performs full member-wise move of the object's bases and non-static members, in their initialization order, using direct initialization with an xvalue argument.
What is the default constructor? Java doesn't require a constructor when we create a class. However, it's important to know what happens under the hood when no constructors are explicitly defined. The compiler automatically provides a public no-argument constructor for any class without constructors.
A move constructor allows the resources owned by an rvalue object to be moved into an lvalue without creating its copy. An rvalue is an expression that does not have any memory address, and an lvalue is an expression with a memory address.
Why does a move constructor requires a default constructor for its members?
The move constructor that you defined default-constructs a member. If you default construct any members, then the default constructor is required for those members.
A constructor (be it regular, copy or move) default initializes the members that are not listed in the member initialization list nor have a default member initialization. B::a
is not in the member initialization list of the move constructor (it doesn't have an initialization list at all) and it has no default member initialization.
Any way around it?
Most simply, use the default move constructor:
B(B&&) = default;
The default move constructor move-constructs the members.
Use the constructor's initializer list to initialize the A
member. As written, the move constructor uses, as the compiler says, the default constructor for A
.
B(B&& b) : a(std::move(b.a)) {}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With