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".
If no user-defined destructor exists for a class and one is needed, the compiler implicitly declares a destructor. This implicitly declared destructor is an inline public member of its class.
Destructors are usually used to deallocate memory and do other cleanup for a class object and its class members when the object is destroyed. A destructor is called for a class object when that object passes out of scope or is explicitly deleted.
A destructor has the same name as the class, preceded by a tilde ( ~ ). For example, the destructor for class String is declared: ~String() . If you do not define a destructor, the compiler will provide a default one; for many classes this is sufficient.
Delete invokes the destructor In turn, since ListItem has member String val, the destructor for String is invoked. Default destructors call destructors of member objects, but do NOT delete pointers to objects. Thus, we need to write destructors that explicitly call delete.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With