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

Ben*_*enj 8 c++ destructor

所以我读了这篇文章:

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

其中讨论了原因:

~Widget() = default;
Run Code Online (Sandbox Code Playgroud)

与以下内容不同:

~Widget() {}
Run Code Online (Sandbox Code Playgroud)

但是,“ = default”大小写与隐式声明的大小写也不同。从某种意义上说,= default实际上并没有为您提供默认值,这有点奇怪。

考虑以下程序:

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;
}
Run Code Online (Sandbox Code Playgroud)

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

orl*_*rlp 7

仅在以下情况下创建隐式定义的move构造函数:B

  • 没有用户声明的副本构造函数;
  • 没有用户声明的副本分配运算符;
  • 没有用户声明的移动分配运算符;
  • 没有用户声明的析构函数;

现在,当您说时~B() = default;,尽管仍然可以获得默认的析构函数,但现在也将其视为用户声明的,因此不会隐式定义move构造函数。

  • @Benj为什么?这只是列出了“简单”析构函数的条件,而不是“默认”或“隐式定义”析构函数。它谈论的是*用户提供的*而不是*用户声明的*,这是一个微妙的区别。不管怎样,在 cppreference wiki 上讨论这种详细程度的细节可能是徒劳的,如果你想像这样真正具体,你应该直接查阅标准。 (2认同)