std::is_trivially_default_constructible 才是标准名称,std::is_trivially_defaultable 不存在;它检查类型是否具有不执行任何操作的隐式默认构造函数,要求所有成员和基类也满足该条件。

std::is_trivially_default_constructible 才是标准名称,std::is_trivially_defaultable 根本不存在 —— 这是常见拼写错误,编译直接报错。
为什么 std::is_trivially_defaultable 编译不过
这是最常踩的坑:C++ 标准库中没有这个类型特征。正确名称是 std::is_trivially_default_constructible(注意后缀是 default_constructible,不是 defaultable)。它定义在 <type_traits></type_traits> 头文件中。
常见错误现象:
error: 'is_trivially_defaultable' is not a member of 'std'- IDE 自动补全误导(某些旧插件或文档缓存残留错误建议)
std::is_trivially_default_constructible 判定的是什么
它检查类型 T 是否拥有**平凡的默认构造函数** —— 即该构造函数不执行任何操作(甚至不隐式初始化内置成员),且满足以下全部条件:
立即学习“C++免费学习笔记(深入)”;
- 是隐式声明的(即用户没写任何构造函数,或只写了非默认构造函数但没禁用默认构造)
- 不是用户提供的(
= default算用户提供的,但若用于类内声明且类满足平凡性要求,仍可能为true) - 所有非静态数据成员和基类都满足
std::is_trivially_default_constructible_v - 不调用任何非平凡的构造逻辑(例如不会触发
std::string的内存分配)
典型场景:做 SBO(small buffer optimization)判断、memcpy-safe 类型筛选、或配合 std::is_trivially_copyable 做 POD-like 类型校验。
实际使用时要注意的边界情况
即使类看起来“空”,也可能返回 false。关键看成员和继承链是否全 trivial:
- 含
std::string、std::vector、用户自定义非平凡构造函数的成员 →false - 含
const或引用成员 → 默认构造函数被隐式删除 →false - 显式写了
T() = default;在类内:若所有成员都 trivial,则仍为true;但若在类外定义(T::T() = default;),则被视为用户提供的,结果为false - 虚基类或虚函数 → 不影响此 trait,但通常意味着类已非 trivial 可复制,需结合其他 trait 综合判断
示例:
struct A { int x; }; // true
struct B { std::string s; }; // false
struct C { const int x; }; // false(默认构造被删除)
struct D { D() = default; int x; }; // true(类内 = default,且成员 trivial)别和 std::is_default_constructible 混用
前者要求“平凡”,后者只要求“能默认构造”(哪怕要调用复杂构造函数)。比如 std::vector<int></int> 是 std::is_default_constructible_v 为 true,但 std::is_trivially_default_constructible_v 一定为 false。
性能影响很关键:只有 trivially_* 类型才适合用 memset、memcpy 或 placement-new + 未初始化内存等底层操作。误用 default_constructible 替代会引发未定义行为。
真正容易被忽略的点是:平凡默认可构造 ≠ 平凡可复制 ≠ 平凡可析构 —— 它们是正交条件,必须分别检查。比如一个类有 trivial 默认构造,但析构函数是 virtual,那它就不是 trivially destructible,也不能随便 memcpy。


















