Reputation: 32428
So I read this post:
How is "=default" different from "{}" for default constructor and destructor?
Which discusses why:
~Widget() = default;
Isn't the same as:
~Widget() {}
However, it's also true that the "=default" case is different than the implicitly declared case. In some sense, =default doesn't actually give you the default, which is kinda odd.
Consider the following program:
class A
{
public:
A(std::string str)
{
m_str = str;
}
~A() = default;
A(A const& rhs)
{
printf("Got copied\n");
m_str = rhs.m_str;
}
A(A&& rhs)
{
printf("Got moved\n");
m_str = std::move(rhs.m_str);
}
std::string m_str;
};
class B
{
public:
B(std::string test) : m_a(test)
{
}
~B() = default;
A m_a;
};
int main()
{
B b("hello world");
B b2(std::move(b));
return 0;
}
Running this program will print "Got copied", unless you comment out the defaulted ~B() in which case it will print "Got moved". So why is this? I think "=default" is pretty confusing considering both this and the implicitly declared destructor are supposed to produce "trivial destructors".
Upvotes: 10
Views: 739
Reputation: 118016
The implicitly-defined move constructor for B
only gets created if
- there are no user-declared copy constructors;
- there are no user-declared copy assignment operators;
- there are no user-declared move assignment operators;
- there are no user-declared destructors;
Now when you say ~B() = default;
, while you still get the default destructor, it's now also considered user-declared, and thus there won't be an implicitly defined move constructor.
Upvotes: 8