2

I'm confused of the rules of default function generation at this situation:

For the simplest class:

Class B{};

It will auto-generated the move constructor.

However, what if for

Class B{ public: ~B(){} }

I think it should be as same as the default deconstructor, will I have a default move constructor at this time? and how could I check it?

class A{
public:
    A() {}
    A(const A& lv) {cout << "a copy ctor." << endl;}
    A(A&& rv) {cout << "a move ctor." << endl;}
};

class B{
public:
    //~B(){}
private:
    A a;
};

int main()
{
    B b;
    B b2(std::move(b));
    return 0;
}

I tried this method, it seems the answer is no, but I'm not sure.

Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
akanesora
  • 81
  • 6
  • Are you aware of the [Rule of Three](https://en.cppreference.com/w/cpp/language/rule_of_three)? Have you conformed? – tadman Jun 26 '23 at 00:58
  • 1
    https://en.cppreference.com/w/cpp/language/move_constructor#Implicitly-declared_move_constructor – songyuanyao Jun 26 '23 at 01:19
  • Defining a constructor (deconstructor is a nonsense word) does not generally affect whether the compiler implicitly generates copy or move constructors. That said (rule of five) if you need to define one of destructor, copy constructor, move constructor, copy assignment, or move assignment to do something non-trivial, then it is necessary to define the others. [Simple tracking of constructor and destructor calls is a trivial exception to that rule - the rule is about classes that manage resources]. – Peter Jun 26 '23 at 03:19
  • [My answer](https://stackoverflow.com/a/72108104/) to a similar, but not quite the same, question applies here as well. It's surprising how many ways people can attempt to find loopholes in what is a very simple concept ("user-declared destructor"). – JaMiT Jun 26 '23 at 05:52

1 Answers1

5

The short answer is "no".

The longer answer is that what matters isn't the content of the body of the dtor, but whether it's declared by the user. Specifically (N4950, [class.copy.ctor]/8):

If the definition of a class X does not explicitly declare a move constructor, a non-explicit one will be implicitly declared as defaulted if and only if

  • X does not have a user-declared copy constructor,
  • X does not have a user-declared copy assignment operator,
  • X does not have a user-declared move assignment operator, and
  • X does not have a user-declared destructor.

So even when you define the dtor to be exactly what the compiler would produce by default, you've still declared it, in which case it's a user-declared dtor, and the compiler no longer generates a move-ctor implicitly (nor move assignment).

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111