Why do we need to use virtual ~A() = default; instead of virtual ~A() {} in C++11?
In Stack Overflow post Checking the object type in C++11, I have the comment:
In C++11 you'll actually want to do
virtual ~A() = default;
Otherwise, you'll lose the implict move constructors.
What is virtual ~A() = default;
for? How come implicit move constructors lost with virtual ~A() {}
?
Solution 1:
The comment is not correct.
Both:
virtual ~A() = default;
and
virtual ~A() {}
are user declared. And the implicit move members are inhibited if the destructor is user declared.
[dcl.fct.def.default]/p4 discusses user-declared and user-provided special members:
A special member function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration.
Solution 2:
In this post https://stackoverflow.com/a/17204598/260127, I have the comment:
In C++11 you'll actually want to do
virtual ~A() = default;
Otherwise, you'll lose the implict move constructors.
The comment is incorrect.
Even default
ed, that destructor is "user-declared" (though note that it is not also "user-provided").
#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 haven't "lost" anything — there was no move functionality there to begin with!
Here is the standard passage that prohibits an implicit move constructor in both cases:
[C++11: 12.8/9]:
If the definition of a classX
does not explicitly declare a move constructor, 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,X
does not have a user-declared destructor, and- the move constructor would not be implicitly defined as deleted.
Bootnote
It wouldn't hurt if a future version of the standard actually listed the precise meanings of terms such as "user-declared". There is, at least, this:
[C++11: 8.4.2/4]:
[..] A special member function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration. [..]
One may assume the distinction here by implication.