std::is_trivially_destructible 返回 true 仅当类型满足三个硬性条件:使用隐式定义析构函数、析构函数非虚、所有基类及非静态成员也均为平凡可析构类型;常见 true 类型包括 int、char*、纯 POD struct 和 std::array。
能跳过析构调用就别遍历——的核心价值不是“判断”,而是“分支优化”。
什么时候
返回 true
它只在类型满足三个硬性条件时返回
:隐式定义析构函数、非虚析构、所有基类和非静态成员也都是 trivially destructible。哪怕你写一个空的
,它就立刻变成
;带
成员?
;有虚函数?
;继承自带自定义析构的基类?
。
常见返回
的类型包括:
、
、纯 POD
(无构造/析构/虚函数/非平凡成员)、
(成员全为
)。
→
→
(析构要释放堆内存)
→
是
,哪怕你没写析构函数
怎么在容器销毁逻辑里真正用起来
STL 内部就是靠这个 trait 跳过无意义的析构循环。比如你实现一个简易 vector,销毁元素时不能一视同仁地对每个元素调用
——对
调用析构是冗余开销,对
不调用则是内存泄漏。
立即学习
“
C++免费学习笔记(深入)
”;
典型模式是模板特化 + 类型萃取:
C知道
CSDN推出的一款AI技术问答工具
下载
注意必须用
(C++17),运行时
会导致未定义行为:对
解引用并调用
是非法的。
和
别混了
这是两个完全不同的关注点:
关心“析构是否根本不需要执行任何操作”,而
只关心“析构函数声明是否为
”。前者决定能否跳过调用,后者决定 RAII 安全边界。
一个
是
析构,但不是 trivially destructible(显式写了析构)
一个
是 trivially destructible,但
在某些旧标准库实现中可能为
(因隐式析构未显式标
,但 C++17 起已保证为
)
两者都为
才适合做 zero-cost RAII 封装(如自定义句柄类)
容易被忽略的编译期陷阱
最常踩的坑是:在模板中用了
,却忘了它是个编译期常量,无法用于运行时分支;或者误以为
和
行为不同——其实它们等价,但前者在需要
上下文(如
)时更易出错。
另一个隐形雷区是模板参数推导:如果函数模板形参是
,而你传入
,那么
推导为
,此时
仍为
(
是 trivially destructible),但若误用成
,反而可能因 cv 限定符处理不当引入 bug。
std::is_trivially_destructiblestd::is_trivially_destructibletrue~MyClass() {}falsestd::stringfalsefalsefalsetrueintchar*structstd::arrayintstd::is_trivially_destructible_vtruestd::is_trivially_destructible_vfalsestruct S { std::string s; };std::is_trivially_destructible_vfalse~T()intstd::string#include
template
void destroy_range(T first, T last) {
if constexpr (std::is_trivially_destructible_v) {
// 什么也不做:内存直接释放即可
} else {
while (first != last) {
first->~T();
++first;
}
}
}
if constexprifint*~int()std::is_nothrow_destructiblestd::is_trivially_destructiblestd::is_nothrow_destructiblenoexceptstruct X { ~X() noexcept {} };noexceptstruct Y { int x; };std::is_nothrow_destructible_vfalsenoexcepttruetruestd::is_trivially_destructible::value std::is_trivially_destructible{} std::is_trivially_destructible_vconstexprif constexprT*const int*Tconst intstd::is_trivially_destructible_vtrueconst intstd::is_trivially_destructible_v> 