std::is_trivially_copyable 用于编译期判断类型是否可安全用 memcpy 搬运内存,要求其字节布局、拷贝构造、析构等均无副作用;常见于序列化、高频小对象复制等场景。

std::is_trivially_copyable 用来干啥
它是个编译期类型特征,告诉你:这个类型能不能安全地用 memcpy 搬运内存。不是“看起来能”,而是“标准保证能”——包括对象的字节布局、析构函数、拷贝构造等全都不带副作用。
常见错误现象:memcpy(&dst, &src, sizeof(T)) 在自定义类上跑飞了,或者值对不上,但 std::is_trivially_copyable_v<t></t> 返回 false 却被忽略。
使用场景:
- 序列化/反序列化时跳过构造/析构,直拷内存
- 高频小对象批量复制(比如粒子系统、GPU数据上传)
- 实现泛型容器的 memcpy 优化分支
注意:可 trivially copyable ≠ 可 trivially default-constructible 或可 trivially destructible,三者独立判断。
立即学习“C++免费学习笔记(深入)”;
怎么查一个类型是不是 trivially copyable
直接用 std::is_trivially_copyable_v<t></t>,C++17 起推荐用 _v 后缀变量模板。
std::is_trivially_copyable 是类模板,要配合 decltype 或显式类型名使用:
struct S { int x; double y; };
static_assert(std::is_trivially_copyable_v<S>); // ✅ 通过
<p>struct D { std::string s; };
static_assert(!std::is_trivially_copyable_v<D>); // ✅ 不通过</p>容易踩的坑:
- 类里有
std::vector、std::string、std::unique_ptr等成员 → 整个类型自动变成 non-trivially-copyable - 即使所有成员都是 POD,只要手动写了拷贝构造函数(哪怕只是
= default),也要看是否满足 trivial 的全部条件(C++ 标准对 trivial 的定义很严格) - 继承链中有虚函数或虚基类 → 不满足
用 memcpy 替代拷贝构造前必须确认的三件事
- 类型必须是
std::is_trivially_copyable_v<t></t> 为 true
- 源和目标对象地址不能重叠(否则用
memmove,但 memmove 不解决语义问题)
- 对象生命周期已正确管理:目标内存必须已分配且未构造,或已析构;不能在未析构的对象上覆写,也不能对未初始化内存调用析构
std::is_trivially_copyable_v<t></t> 为 true
memmove,但 memmove 不解决语义问题)性能影响:
- 对小对象(≤ 几十个字节),
memcpy通常比默认拷贝快 2–5 倍(无函数调用开销、无成员逐个访问) - 对大对象,现代编译器常把默认拷贝内联成
memcpy,手动写未必有收益,反而可能阻碍优化
兼容性注意:
- C++11 起支持该 trait,但部分老 STL 实现(如早期 libstdc++)对某些模板特化不完整,建议搭配编译器版本检查
-
std::is_trivially_copyable对 union 类型行为依赖实现细节,慎用于含非 trivial 成员的 union
为什么有时候 static_assert 通过了,memcpy 还出错
最常见原因不是类型问题,而是误用场景:
把
memcpy用在指针所指对象上,但忘了指针本身是 trivially copyable,而它指向的内容未必是
(例如std::is_trivially_copyable_v<int>></int>是true,但memcpy(p1, p2, sizeof(int))只复制指针值,不是内容)对齐没对齐:源/目标地址未按
alignof(T)对齐,触发未定义行为(尤其在 ARM 或开启严格对齐检查时)对象含 padding 字节,且代码逻辑错误依赖 padding 内容(trivially copyable 不保证 padding 可读/可写)
移动语义介入:如果类型同时是
std::is_move_constructible,但你强制 memcpy,可能绕过 move 构造逻辑,导致资源重复释放(比如两个对象都以为自己拥有同一块堆内存)
这事的核心不在“能不能 memcpy”,而在于“你有没有真正控制住对象的构造、生命周期和内存布局”。稍一松懈,std::is_trivially_copyable_v<t></t> 就从安全锁变成幻觉开关。









