使用memcpy拷贝含std::string的结构体失败问题咨询
问题分析与解决方案
一、为什么会出现这种现象?
你代码里的核心问题有两个:
- memcpy的拷贝长度参数错误
你用sizeof(&ValuesOut)作为拷贝长度,这是取指针变量的大小——在64位系统下指针固定为8字节。而你的Test1结构体实际大小是48字节(int占4字节+内存对齐填充4字节+std::string内部成员占40字节),所以memcpy只拷贝了前8字节,刚好覆盖int Value的内容,std::string Text的部分完全没被拷贝,这就是ValuesOut.Text为空的原因。 - 即使拷贝长度正确,memcpy也不适合拷贝含std::string的结构体
std::string不是POD(普通旧数据类型),它内部持有指向堆内存的指针来存储实际字符串内容。memcpy是浅拷贝,只会复制string对象的内部指针,不会复制指针指向的堆内存。这会导致两个string对象共享同一块堆内存,当它们析构时会重复释放这块内存,触发未定义行为(程序崩溃、内存损坏等)。
另外你疑惑的“结构体变量地址大小为8但结构体本身大小为48”:&ValuesOut是指向Test1的指针,sizeof(&ValuesOut)是指针的大小,和结构体本身的大小无关——64位系统指针都是8字节,32位是4字节,不管它指向的对象多大。
二、解决方案
1. 最安全便捷的方式:用结构体赋值
直接用ValuesOut = Values;替换memcpy操作。C++的结构体赋值会自动调用成员的拷贝构造函数,对于std::string来说就是深拷贝,既安全又和memcpy一样便捷,完全不需要手动处理每个字段。
修改后的关键代码:
// 替换原来的memcpy行 ValuesOut = Values;
2. 如果必须用类似memcpy的批量拷贝(不推荐)
只有当结构体是POD类型时,memcpy才是合法安全的。你有两种选择:
- 把std::string换成固定大小的char数组,比如
char Text[64];,这样结构体变成POD类型,memcpy可以正常使用,但字符串长度会受限制。 - 使用
std::copy替代memcpy,但本质上和结构体赋值逻辑一致,代码反而更繁琐。
总结
不要用memcpy拷贝含非POD类型(比如std::string、std::vector等)的结构体,直接用赋值操作是最省心且安全的方案,完全满足你“便捷操作多字段结构体”的需求。
内容的提问来源于stack exchange,提问作者Failflood
相关产品推荐
相关产品推荐

