结构体中std::string字段写入std::fstream的疑问:为何写入值而非指针
问题描述
示例结构体:
struct Person { std::string Name; int Age; };
写入fstream的代码:
Person p; p.Name = "Mike"; p.Age = 21; stream.write((char*)&p, sizeof(p));
疑惑点:使用write()函数将Person变量写入fstream时,明明std::string内部通过指针管理字符串,但看起来写入的是"Mike"这个实际值;可如果是const char*类型的话,写入的只是字符串的地址。为什么会有这种区别?
解答
首先纠正一个关键误解:你觉得写入的是"Mike"实际值,其实根本不是。
std::string的内部结构(不同编译器实现有差异,但核心逻辑一致)一般包含几个成员:指向堆内存的指针、当前字符串长度、内存容量。当你调用write((char*)&p, sizeof(p))时,写入的只是std::string对象本身的这几个成员数据,并不会自动去写它指向的堆内存里的字符串内容。
那为什么你会误以为写入了"Mike"?这是因为**小字符串优化(SSO)**机制:当字符串长度较短(比如"Mike"只有4个字符),大部分std::string的实现会把字符串直接存在对象内部的固定缓冲区里,不会去堆上分配内存。这时候你写入std::string对象时,缓冲区里的"Mike"刚好被一起写入文件。但如果换成一个超过SSO缓冲区大小的长字符串,你写入的就只是堆内存的地址,后续读出来时这个地址已经无效,自然拿不到字符串内容。
而const char*本身就是一个指针变量,它存储的就是字符串的内存地址,所以用write()写入时,自然只会把这个地址值写入文件,不会涉及它指向的实际字符串内容。
总结:
write()的行为是固定的:只写入变量本身的二进制数据,不会自动递归处理它指向的堆内存std::string的SSO机制让小字符串场景下出现了"写入实际内容"的假象,本质还是写入对象自身的二进制数据const char*本身就是地址类型,所以写入的就是地址值
内容的提问来源于stack exchange,提问作者ThewyRogue99
相关产品推荐
相关产品推荐

