为什么 "=default" 析构函数与隐式声明的析构函数不同?

Why is a "=default" destructor different than the implicitly declared destructor?

本文关键字:析构函数 声明 default 为什么      更新时间:2023-10-16

所以我读了这篇文章:

默认构造函数和析构函数的"=default"与"{}"有何不同?

其中讨论了原因:

~Widget() = default;

与以下不同:

~Widget() {}

但是,"=default"情况与隐式声明的情况也不同。 从某种意义上说,=default 实际上并没有给你默认值,这有点奇怪。

请考虑以下程序:

class A
{
public:
A(std::string str)
{
m_str = str;
} 
~A() = default;
A(A const& rhs)
{
printf("Got copiedn");
m_str = rhs.m_str;
}
A(A&& rhs)
{
printf("Got movedn");
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;
}

运行此程序将打印"已复制",除非您注释掉默认的~B((,在这种情况下,它将打印"已移动"。 这是为什么呢? 我认为"=default"非常令人困惑,考虑到这一点和隐式声明的析构函数应该产生"琐碎的析构函数"。

B仅当

  • 没有用户声明的复制构造函数;
  • 没有用户声明的复制赋值运算符;
  • 没有用户声明的移动分配运算符;
  • 没有用户声明的析构函数;

现在,当您说~B() = default;时,虽然您仍然获得默认析构函数,但它现在也被认为是用户声明的,因此不会有隐式定义的移动构造函数。