非平凡的析构函数使类具有非平凡的可构造性
Non-trivial destructor make class non-trivially-constructible
考虑以下代码:
#include <type_traits>
struct T {};
static_assert(std::is_trivially_destructible< T >{});
static_assert(std::is_trivially_default_constructible< T >{});
struct N { ~N() { ; } };
static_assert(!std::is_trivially_destructible< N >{});
static_assert(!std::is_trivially_default_constructible< N >{});
它使用clang 3.7.0
进行了良好的编译:实例。但总结标准:
如果以下全部为真,则类T的默认构造函数是琐碎的(即不执行任何操作):
- 构造函数不是用户提供的(即,是隐式定义或默认的)
- T没有虚拟成员函数
- T没有虚拟基类
- T没有具有默认初始值设定项的非静态成员。(自C++11起)
- T的每个直接基都有一个平凡的默认构造函数
- 类类型的每个非静态成员都有一个琐碎的默认构造函数
正如我所看到的,并没有依赖于析构函数的琐碎性。
我错过了什么?是clang
错误吗?
附加
我找到了一个变通方法:是static_assert(__has_trivial_constructor( N ));
内置的类型特性。在clang
、gcc
和MSVC
中都有支持。
对于类型性状的is_noexcept_constructible
家族,也有变通方法。
此问题包含在LWG问题2116:std::swap noexcept(什么?)中,我们可以从std::is_trivialy_default_constructible:的cppreference部分看到这一点
在许多实现中,is_nothrow_default_constructible还检查析构函数是否抛出,因为它实际上是noexept(T()):GCC错误51452 LWG问题2116
它似乎只谈论CCD_ 8,但如果我们详细阅读这个问题,我们会发现它也适用于这里。
如果我们遵循gcc错误报告,也许会更容易:[DR2116]has_nothrow_.*首先引用的构造函数错误说:
检测另一行可构建性的特征是有缺陷的,因为它们受到对象是否具有另一行dtor的影响;destruction是在noexcept(…)运算符中的完整表达式求值结束时调用的。他们都使用构建临时内部noexcept的模式,而他们应该使用放置新的
这明确地说明了LWG问题中真正提到的内容,最终说:
is_nothrow_constructible是在is_constructable的术语中定义的,is_construct是通过查看一个假设变量并询问变量定义是否已知不会抛出异常来定义的。该问题声称,在给定上下文的情况下,这也会检查类型的析构函数,因此,如果析构函数可能引发,则会返回false。如果构造函数为noexcept(true),而析构函数为noexception(false),则至少有一个实现(Howard的)返回false。因此,这不是一个紧张的解释。问题是要求将其定义为新的放置,而不是临时对象,以使is_nothrow_constructible只查看构造函数的noexcept状态,而不查看析构函数。
这也影响了依赖于std::is_trivialy_constructible的CCD_ 9,其作用与CCD_
但是变量定义不调用任何非平凡的操作
- 什么时候调用组成单元对象的析构函数
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 内联映射初始化的动态atexit析构函数崩溃
- 什么时候调用析构函数
- 优先顺序:智能指针和类析构函数
- C++-明确何时以及如何调用析构函数
- 使用基类指针创建对象时,缺少派生类析构函数
- 在c++中使用向量时,如何调用构造函数和析构函数
- 重载运算符new[]的行为取决于析构函数
- 我需要知道编译器如何在cpp中使用析构函数
- 为什么在使用转换构造函数赋值后调用C++类的析构函数?
- 析构函数调用
- 通过引用传递-为什么要调用这个析构函数
- 对具有动态分配的内存和析构函数的类对象的引用
- 重载 -> shared_ptr 个实例中的箭头运算符<interface>,接口中没有纯虚拟析构函数
- C++成员的析构函数顺序与shared_ptr
- C++ 防止在映射中放置()时调用析构函数
- 在这种情况下显式调用时,std::cout 如何更改析构函数的行为?
- 调用析构函数以释放动态分配的内存
- 不命名构造函数和析构函数上的类型错误