Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does a move constructor require a default constructor for its members?

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?

like image 677
ynimous Avatar asked Sep 02 '16 16:09

ynimous


People also ask

Why is default constructor necessary?

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.

What does a default move constructor do?

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.

Do you always need a default constructor?

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.

What is the move constructor?

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.


2 Answers

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.

like image 175
eerorika Avatar answered Sep 19 '22 22:09

eerorika


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)) {}
like image 40
Pete Becker Avatar answered Sep 21 '22 22:09

Pete Becker