Why do we need to use virtual ~ A () = default; instead of virtual ~ A () {} in C ++ 11?

In a Stack Overflow post Checking the type of an object in C ++ 11 , I have a comment:

In C ++ 11, you really want to do virtual ~A() = default; Otherwise, you will lose implict move constructors.

What is virtual ~A() = default; for? How does the implicit movement of constructors lost with virtual ~A() {} occur?

+49
c ++ c ++ 11 destructor virtual-functions
Jun 20 '13 at 19:00
source share
3 answers

The comment is incorrect.

AND

 virtual ~A() = default; 

and

 virtual ~A() {} 

user is declared . And implicit move elements are blocked if a destructor is declared.

[dcl.fct.def.default] / p4 discusses user-declared and special user elements:

A special member function is provided to the user if it is declared by the user and is clearly not defaulted or deleted by its first declaration.

+42
Jun 20 '13 at 19:26
source share

In this post, https://stackoverflow.com/a/312618/2323/ I have a comment:

In C ++ 11, you really want to do virtual ~A() = default; Otherwise, you will lose implict move constructors.

The comment is incorrect.

Even default ed, the "declared by the user" destructor (although note that it is also not "provided by the user").

 #include <iostream> struct Helper { Helper() {} Helper(const Helper& src) { std::cout << "copy\n"; } Helper(Helper&& src) { std::cout << "move\n"; } }; struct A { virtual ~A() {} Helper h; }; struct B { virtual ~B() = default; Helper h; }; struct C { Helper h; }; int main() { { A x; A y(std::move(x)); // outputs "copy", because no move possible } { B x; B y(std::move(x)); // outputs "copy", because still no move possible } { C x; C y(std::move(x)); // outputs "move", because no user-declared dtor } } 

Live demo :

+ g ++ - 4.8 -std = C ++ 11 -O2 -Wall -pthread main.cpp
+. / a.out
copy
copy
move

So you have not โ€œlostโ€ anything; there were no moving functions here.

Here is a standard excerpt prohibiting an implicit move constructor in both cases:

[C++11: 12.8/9]: If the definition of class X does not explicitly declare the move constructor, it will be declared implicitly as default, if and only if

  • X does not have a user-declared copy constructor,
  • X does not have a user-declared copy destination operator,
  • X does not have a user-declared move destination operator,
  • X does not have a user-declared destructor and
  • the move constructor will not be implicitly defined as remote.



Bootnote

It would not hurt if the future version of the standard actually indicated the exact meaning of terms such as "user-declared". At least this:

[C++11: 8.4.2/4]: [..] A special member function is provided to the user if it is declared by the user and is clearly not defaulted or deleted in its first declaration. [..]

Here you can distinguish this difference.

+27
Jun 20 '13 at 19:33
source share

This comment is incorrect.

Instead of providing your own move constructor if you want the compiler to provide one, one of the requirements is that it expects the destructor to be provided to them too, i.e. trivial destructor. However, the current standard is pretty strict when an implicit implementation can be provided - in accepting how the user gives the destructor. Everything that is declared by the user is considered that the user takes matters into their own hands and, therefore, not only this

 ~A() { โ€ฆ } 

but this one

 ~A() = default; 

causes the compiler not to provide an implicit destructor. Firstly, it is a definition and, therefore, a declaration; the second is just a declaration. In both cases, the destructor is declared by the user and thus prevents the compiler from providing an implicit move constructor.

I believe that the rationale for the requirement is that during the move, the resource of the object is moved to another object, leaving the original object in a state where it does not have resources in dynamic storage; but if your class does not have such resources, then it can be trivially moved, destroyed, etc. When you declare a non-trivial destructor, itโ€™s key for the compiler that the resources you manage in the class are not trivial and that you basically would need to provide a nontrivial move, so the compiler does not provide it.

+5
Jun 20 '13 at 19:05
source share



All Articles