memcpy仅对平凡可复制类型(std::is_trivially_copyable_v为true)安全:要求无虚函数、无非平凡成员(如std::string)、无自定义构造/析构,否则引发未定义行为而非仅性能下降。

能用 memcpy 加速拷贝,但前提是 std::is_trivially_copyable_v<t></t> 在编译期就返回 true;否则就是未定义行为(UB),不是慢一点,而是随时崩溃。
为什么 memcpy 不能随便套在任意 struct 上
编译器不会拦你调用 memcpy(dst, src, sizeof(T)),但它只对满足平凡可复制条件的类型安全——这意味着:所有成员、基类都无构造/析构逻辑,无虚函数表指针(vptr),内存是连续纯数据块。
- 含
std::string成员 →std::is_trivially_copyable_v<t></t>为false,memcpy后接收端拿到的是悬垂指针,解引用即崩溃 - 带
virtual函数的类 →false,vptr 被位拷贝后指向发送端旧地址,调用虚函数跳转到非法内存 - 哪怕只写了
MyClass(const MyClass&) = default;,只要成员里有非平凡类型,整个类型仍不满足条件 -
std::is_trivially_copyable_v<int></int>是false,引用类型不参与位拷贝,别误用
怎么确认你的 struct 真的能 memcpy
靠猜会出生产事故。必须用 static_assert 在编译期钉死:
struct SensorReading {
uint64_t timestamp;
float values[3];
uint8_t status;
};
static_assert(std::is_trivially_copyable_v<sensorreading>, "SensorReading must be safe for memcpy");</sensorreading>
- 检查目标必须是最终使用的完整类型,比如查
SensorReading,不是std::vector<sensorreading></sensorreading> - 继承链中任意一层引入虚函数,整个派生类立刻变成
false,哪怕你没加新字段 - 前置声明的类(
class Foo;)会让 trait 返回false,不报错但结果不可信,容易漏检 - 如果用了
private/protected成员,不影响trivially_copyable,但可能破坏标准布局(std::is_standard_layout_v)——这关系到跨平台 reinterpret_cast 是否安全
memcpy 后 reinterpret_cast 接收端一定安全吗
不自动安全。std::is_trivially_copyable_v<t></t> 只保证“位拷贝后值不变”,不保证两端 ABI 一致:
- 字段偏移可能因
#pragma pack缺失或编译器默认对齐差异而错位 -
int宽度不统一(嵌入式平台可能是 16 位),必须用int32_t这类固定宽度类型 -
字节序仍是问题:
trivially_copyable≠ “已转网络序”,htons/ntohl该用还得用 - 接收端
reinterpret_cast<t>(buf)</t>合法的前提是:发送端也用相同 layout 的Tmemcpy,且两端对T的内存解释完全一致(包括 padding、对齐、大小端)
真正难的从来不是写那行 static_assert,而是确保整个类型体系从根开始就没悄悄引入虚函数、非平凡成员或自定义操作符——这些改动往往藏在第三方头文件或深层基类里,一不小心就让 memcpy 崩溃在运行时。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











