【问题标题】:Can T have a destructor when std::is_trivial_v<T> is true?当 std::is_trivial_v<T> 为真时,T 可以有析构函数吗?
【发布时间】:2020-04-14 12:43:09
【问题描述】:
#include <type_traits>

struct A
{
    ~A() {}
};

int main()
{
    static_assert(std::is_trivial_v<A>); // error   
}

如果A 有析构函数,std::is_trivial_v&lt;A&gt; 将是false 似乎很明显。

但是,从std::is_trivialcppref page 来看,没有什么要求A 不能有析构函数。

可以 T std::is_trivial_v&lt;T&gt; 为真时有析构函数吗?

【问题讨论】:

    标签: c++ standards destructor typetraits c++-concepts


    【解决方案1】:

    你需要在兔子洞里走得更远。 cppreference 页面说琐碎的类型需要是TriviallyCopyable。如果您访问该页面,它需要一个

    Trivial未删除的析构函数

    如果我们访问该链接,我们有

    简单的析构函数

    如果满足以下所有条件,则类 T 的析构函数是微不足道的:

    • 析构函数不是用户提供的(也就是说,它要么被隐式声明,要么在其第一个声明中显式定义为默认值)
    • 析构函数不是虚拟的(即基类析构函数不是虚拟的)
    • 所有直接基类都有微不足道的析构函数
    • 类类型(或类类型数组)的所有非静态数据成员都有普通的析构函数

    普通析构函数是不执行任何操作的析构函数。具有普通析构函数的对象不需要删除表达式,并且可以通过简单地释放它们的存储来处理。所有与 C 语言兼容的数据类型(POD 类型)都可以简单地破坏。

    所以,是的,它需要一个微不足道的析构函数,而您的用户提供的空析构函数并不被认为是微不足道的。

    您可以“编写”析构函数并将其视为微不足道的唯一方法是使用

    ~ClassName() = default;
    

    【讨论】:

    • tl;博士在学习/研究时阅读了不止一两段!
    【解决方案2】:

    std::is_trivial_v&lt;T&gt; 为真时,T 可以有析构函数吗?

    它不能有非平凡的析构函数。如果满足以下所有条件,则类 T 的析构函数是微不足道的:

    • 析构函数不是用户提供的(意思是,它要么被隐式声明,要么被明确定义为默认的第一个 声明)
    • 析构函数不是虚拟的(即基类析构函数不是虚拟的)
    • 所有直接基类都有微不足道的析构函数
    • 类类型(或类类型数组)的所有非静态数据成员都有普通的析构函数

    【讨论】:

    • 为什么 cppref 页面没有提供相同的定义?
    • @xmllmx 因为这些定义在描述析构函数的页面上。
    • @xmllmx 描述std::is_trivial的页面链接here,后者链接here,后者又链接到the same explanation关于虚拟析构函数。
    • @xmllmx 如果您提出这样的(language-lawer 类型)问题,您可能更希望了解 C++ 标准而不是 cppreference。例如,当前 Draft 版本中的相关部分是class.dtor/8
    【解决方案3】:

    当一个类型是微不足道的,这意味着它暗示它可以被微不足道地破坏。
    像您所做的那样显式定义一个方法将不符合此约束。
    但是你可以做的是:

    struct A {
        ~A() = default;
    };
    
    static_assert(std::is_trivial<A>::value);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-24
      • 2017-05-14
      • 1970-01-01
      • 2016-11-26
      • 2023-03-21
      • 2018-11-22
      • 2015-08-21
      • 2022-01-08
      相关资源
      最近更新 更多