C++对象如何序列化和反序列化?(Boost/Cereal库)

cereal更轻量、头文件即用,Boost功能全但需编译;核心是为类定义serialize函数并选择对应归档类型(JSON/二进制/XML)执行序列化与反序列化。

用 Boost.Serialization 或 cereal 库做 C++ 对象序列化和反序列化,核心就两点:让类支持存取逻辑 + 选对存档类型(文本/二进制/XML)。cereal 更轻量、头文件即用;Boost 功能更全但依赖编译。下面直接说怎么写、怎么用。

让类可序列化:定义 serialize 成员或友元

cereal 要求你为类提供一个 serialize 成员函数(或非成员友元),它接收一个归档对象(如 cereal::JSONOutputArchive),把成员变量按顺序传给它。Boost 同理,只是接口名略有不同。

例如:

struct Person {
  std::string name;
  int age;
  std::vector scores;

  template
  void serialize(Archive& ar) {
    ar(CEREAL_NVP(name), CEREAL_NVP(age), CEREAL_NVP(scores));
  }
};

选择归档类型并执行序列化

序列化就是把对象“写进”某种格式的归档。cereal 支持 JSON、XML、二进制;Boost 还支持宽字符和自定义流。

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

  • JSON 输出:cereal::JSONOutputArchive ar{ofs}; ar(obj);
  • 二进制输出:cereal::BinaryOutputArchive ar{ofs}; ar(obj);
  • Boost 示例:boost::archive::text_oarchive ar(ofs); ar & obj;

注意:二进制归档不跨平台(字节序、类型大小需一致);JSON/XML 更通用,但体积大、稍慢。

反序列化:从归档中重建对象

反序列化是序列化的逆过程,用对应输入归档类型读取数据,自动填充对象字段。前提是对象已构造好(或用默认构造),且归档内容与序列化时结构完全匹配(字段名、顺序、类型)。

  • cereal:cereal::JSONInputArchive ar{ifs}; ar(obj);
  • Boost:boost::archive::text_iarchive ar(ifs); ar & obj;

若字段名不一致或新增/删减字段,cereal 可通过 CEREAL_OPTIONAL 或版本控制处理;Boost 需显式实现 save_construct_data/load_construct_data 等机制。

常见坑和建议

实际用的时候容易卡在这几处:

  • 基类没声明虚析构?多态序列化会出错 —— 记得加 virtual ~Base() = default;
  • 指针成员(尤其裸指针)默认不递归序列化 —— 用 cereal::memory_input_archive 或智能指针 + 显式处理
  • STL 容器、std::string、智能指针等开箱即用;自定义容器需单独特化 serialize
  • cereal 头文件全在 下,别漏 include;Boost 需链接 libboost_serialization

基本上就这些。选 cereal 快速上手,选 Boost 需长期维护或要深度定制。两者都不需要宏或代码生成,纯 C++ 模板搞定。