C++怎么实现序列化_C++对象持久化教程【存储】

2次阅读

二进制序列化必须用 write() 而非

C++怎么实现序列化_C++对象持久化教程【存储】

std::ofstream 写二进制时没调用 write() 会丢数据

直接用 operator 输出对象,本质是格式化文本输出,不仅不保存原始内存布局,还会跳过私有成员、触发隐式转换、丢失对齐信息。真正做二进制序列化必须绕过流操作符,用 <code>write() 手动写入字节块。

  • 仅当类是 trivially copyable(如纯 POD 类型)时,才能安全地用 reinterpret_cast<char>(&obj)</char> + sizeof(obj) 配合 write()
  • 指针虚函数std::Stringstd::vector 的类,不能直接 memcpy —— 这些字段存的是运行时地址或上指针,序列化后反序列化会解引用非法内存
  • 写文件前务必检查 is_open()good(),否则静默失败;写完要调 close() 或确认 flush() 已执行

boost::serialization 却连不上 archive

Boost.Serialization 不是头文件-only 库,#include <boost></boost> 只是声明,链接时必须显式加入 -lboost_serializationlinux/macos)或对应 .lib(windows)。漏掉这步,编译能过,但链接报 undefined reference to `boost::archive::binary_oarchive_impl::...'

  • 确保安装的是完整 Boost(非仅头文件版),且版本 ≥ 1.56(旧版 binary archive 有 ABI 兼容问题)
  • 自定义 serialize() 函数必须声明在 public 区,且接受 Archive&const unsigned int 两个参数
  • 若类含模板成员或继承关系,需额外用 BOOST_CLASS_EXPORT 导出类型,否则反序列化时无法识别

自己写 save()/load() 但跨平台读写失败

不同系统默认字节序(endianness)、结构体填充(padding)、int/long 大小都可能不同。比如 x86_64 Linux 下 long 是 8 字节,Windows MSVC 下是 4 字节 —— 直接写 sizeof(long) 会导致读取错位。

  • 固定宽度类型优先:用 int32_tuint64_t 替代 intunsigned long
  • 结构体加 #pragma pack(1)[[gnu::packed]] 消除填充,但注意性能代价(非对齐访问在某些 CPU 上慢甚至崩溃)
  • 手动处理字节序:存前用 htons()/htonl(),读后用 ntohs()/ntohl(),别依赖本地 endian 宏做条件编译

反序列化时 std::vector 数据全为零或越界

因为只写了 vector 的 size(比如 v.size()),却没写实际元素内容。或者写了 size 后,用 resize() 分配空间,再逐个 read(),但忘了 resize() 不保证内存连续 —— 实际上 std::vector::data() 才是合法的读写起点。

立即学习C++免费学习笔记(深入)”;

  • 正确做法:先读 size → v.resize(n) → 用 v.data() 获取首地址 → read(reinterpret_cast<char>(v.data()), n * sizeof(T))</char>
  • 若 vector 元素是非 trivial 类型(如含 string 的 Struct),不能整块读,得循环单个序列化
  • 读之前务必检查文件剩余长度,避免 read() 超出边界导致 failbit 置位却不报错

序列化不是“把内存 dump 出去”那么简单。哪怕一个 std::string 字段,背后就涉及堆分配地址、长度、容量三个值,而反序列化时你得重建整个堆状态——这点最容易被当成“小问题”跳过去,结果调试半天才发现是 string 的内部指针没重置。

text=ZqhQzanResources