Chris Sketch
Chris Sketch

Reputation: 68

Necessity of default constructor for members

I am confused by a compiler error I'm receiving with C++14. It concerns the necessity of a default constructor for member variables. In the code below, class A does not have a default constructor. class B has a member of type A that it move assigns. The compiler complains about the lack of default constructor for A, even though I'm not explicitly calling it anywhere. Is there some implicit call to the default constructor of A happening in the constructor of B that I'm missing? My understanding was that if you initialize the members of B in the constructor of B, then the default constructor is not necessary.

The code in main works fine when B is commented out. What is essentially the same thing in the constructor of B does not work.

Thank you,

#include <utility>                                                                                                                                                                                                                     

class A { 
public:
  A(int x) : _x{x} {}
  A(A &&other) : _x{other._x} {}
  A &operator=(A &&other) { _x = other._x; }
private:
  int _x; 
};

class B { 
public:
  B() {
    A a(2);
    _a = std::move(a);
  }
private:
  A _a; 
};

int main() {
  A b(1);
  A a = std::move(b);
  return 0;
}
~/move.cpp: In constructor ‘B::B()’:
~/move.cpp:17:7: error: no matching function for call to ‘A::A()’
   B() {
       ^
~/move.cpp:7:3: note: candidate: A::A(A&&)
   A(A &&other) : _x{other._x} {}
   ^
~/move.cpp:7:3: note:   candidate expects 1 argument, 0 provided
~/move.cpp:5:3: note: candidate: A::A(int)
   A(int x) : _x{x} {}
   ^
~/move.cpp:5:3: note:   candidate expects 1 argument, 0 provided

Upvotes: 0

Views: 84

Answers (2)

Klischeepunk
Klischeepunk

Reputation: 36

B() { <- tries to call A(); 
B() : _a(2) <- calls A(int x); 
B() : _a(A(2)) <- Calls A(const A&) and A(int x)
B(A a) : _a(std::move(a)) <- calls A(A &&other)

Upvotes: 0

cigien
cigien

Reputation: 60208

Is there some implicit call to the default constructor of A happening in the constructor of B that I'm missing?

Yes. From the reference

Before the compound statement that forms the function body of the constructor begins executing, initialization of all direct bases, virtual bases, and non-static data members is finished.

(emphasis mine)

So in the constructor

B()   {
 // ^ here

before the opening brace, the member _a is initialized. But since there's no default constructor, you get an error. You can avoid this by initializing it explicitly

B() : _a(42) {

Upvotes: 2

Related Questions