std::is_trivially_copyable 是编译期布尔常量,用于判断类型T是否可被memcpy安全复制且语义等价于拷贝构造/赋值;仅当为true时才能安全替换为memcpy以获得性能提升。

std::is_trivially_copyable 是什么类型特征
它是一个编译期布尔常量,用于判断某个类型 T 是否满足「可被 memcpy 安全复制」的底层要求。不是“看起来能拷贝”,而是编译器保证:对该类型的对象做 memcpy,结果与调用其拷贝构造函数或赋值运算符**语义等价**。
为什么影响 memcpy 性能
当 std::is_trivially_copyable_v 为 true,你才能安全地把 std::copy 或手写循环替换成 memcpy —— 否则行为未定义。性能提升来自两方面:
-
memcpy是编译器高度优化的内置操作,可能展开为单条 CPU 指令(如rep movsb或向量化指令) - 绕过构造/析构逻辑、虚表指针处理、成员函数调用开销
但注意:仅当类型满足 trivially copyable,且内存布局连续(如 std::vector 的 data())、对齐满足要求时,memcpy 才真正生效。
哪些类型通常不满足 trivially copyable
以下类型会让 std::is_trivially_copyable_v 返回 false,禁止直接 memcpy:
立即学习“C++免费学习笔记(深入)”;
- 含非 trivial 拷贝构造函数、赋值运算符或析构函数的类(例如有
std::string成员) - 含虚函数或虚基类的类(vptr/vtable 指针不能简单复制)
- 含引用成员或 const 成员的类(复制后无法维持引用绑定或 const 语义)
- 含用户定义的移动操作但未显式声明拷贝操作的类(可能隐式删除拷贝)
struct Bad {
std::string s; // 非 trivial
virtual void f() {} // 有虚函数
};std::is_trivially_copyable_v 是 false —— 对它的对象调用 memcpy 会破坏内部指针,引发崩溃或静默数据损坏。
怎么安全地用 memcpy 替代拷贝
必须同时验证三件事:
- 类型是 trivially copyable:
static_assert(std::is_trivially_copyable_v); - 源和目标内存不重叠(否则用
memmove) - 地址对齐满足要求(尤其对
float/double/__m128等)
典型安全用法:
templatevoid fast_copy(T* dst, const T* src, size_t n) { static_assert(std::is_trivially_copyable_v , "T must be trivially copyable"); memcpy(dst, src, n * sizeof(T)); }
最容易被忽略的是:即使 T 是 trivially copyable,若 T 包含指针(比如 struct { int* p; };),memcpy 只复制指针值,不复制它指向的数据 —— 这不是语言限制,而是语义设计,得你自己想清楚要不要深拷贝。










