C++ Boost Serialization 指针与引用序列化详解
深入解析 C++ Boost.Serialization 库中指针与引用的序列化行为,通过原始指针、scoped_ptr 及引用类型的代码示例,阐明序列化的是对象内容而非地址,并说明其对 C++11 智能指针的支持现状。
核心机制:序列化对象而非地址
Boost.Serialization 库在处理指针和引用时遵循“序列化合约对象”的原则。由于指针仅存储内存地址,而该地址在不同进程或重启后的程序中将失效,直接序列化地址无实际意义。因此,当序列化指针或引用时,Boost.Serialization 会追溯其指向的实际对象并进行序列化;反序列化时,也会重新构造一个全新的对象实例。
实战操作与代码示例
第1步:使用原始指针进行序列化
目的:演示动态分配的普通对象如何通过指针被正确序列化与还原,验证反序列化后对象内容与原对象一致但地址不同。
关键逻辑:
- 类内部需定义友元
boost::serialization::access并重载serialize函数以告知库如何保存成员变量。 - 使用
boost::archive::text_oarchive写入,boost::archive::text_iarchive读取。 - 反序列化后,指针变量会被赋值为一个新分配对象的地址,必须手动管理内存以避免泄漏。
代码实现:
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <iostream>
#include <sstream>
std::stringstream ss;
class animal
{
public:
animal() = default;
animal(int legs) : legs_{legs} {}
int legs() const { return legs_; }
private:
friend class boost::serialization::access;
template <typename Archive>
void serialize(Archive &ar, const unsigned int version) { ar & legs_; }
int legs_;
};
void save()
{
boost::archive::text_oarchive oa{ss};
animal *a = new animal{4};
oa << a;
std::cout << std::hex << a << '\n';
delete a;
}
void load()
{
boost::archive::text_iarchive ia{ss};
animal *a;
ia >> a;
std::cout << std::hex << a << '\n';
std::cout << std::dec << a->legs() << '\n';
delete a;
}
int main()
{
save();
load();
}
在此示例中,oa << a 触发了对 a 指向的 animal 对象的序列化。加载时,ia >> a 会创建一个全新的 animal 对象,并更新指针 a 指向该新地址。输出结果显示两次输出的十六进制地址不同,但 legs()
第2步:使用 scoped_ptr 智能指针进行序列化
目的:利用 Boost 提供的智能指针自动管理内存,简化序列化过程中的资源清理工作。
准备条件:包含头文件 <boost/serialization/scoped_ptr.hpp> 和 <boost/scoped_ptr.hpp>。
注意事项:Boost.Serialization 原生支持 boost::shared_ptr 时需包含 <boost/serialization/shared_ptr.hpp>。但对于 C++11 标准库中的 std::shared_ptr 和 std::unique_ptr,旧版 Boost.Serialization 并不直接支持,可能需要自定义特化或升级库版本。
代码实现:
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/scoped_ptr.hpp>
#include <boost/scoped_ptr.hpp>
#include <iostream>
#include <sstream>
using namespace boost::archive;
std::stringstream ss;
class animal
{
public:
animal() = default;
animal(int legs) : legs_{legs} {}
int legs() const { return legs_; }
private:
friend class boost::serialization::access;
template <typename Archive>
void serialize(Archive &ar, const unsigned int version) { ar & legs_; }
int legs_;
};
void save()
{
text_oarchive oa{ss};
boost::scoped_ptr<animal> a{new animal{4}};
oa << a;
}
void load()
{
text_iarchive ia{ss};
boost::scoped_ptr<animal> a;
ia >> a;
std::cout << a->legs() << '\n';
}
int main()
{
save();
load();
}
使用 scoped_ptr 可以自动在作用域结束时释放内存,避免了手动 delete 的繁琐。关键在于类定义依然保持不变,序列化头文件的引入使得库能识别并正确处理智能指针类型。
第3步:使用引用进行序列化
目的:展示对局部对象引用的序列化过程,证明引用序列化本质上是对其绑定对象的序列化。
操作顺序:
- 定义本地对象
animal a{4}。 - 创建引用
animal &r = a。 - 将引用
r传入存档对象。
代码实现:
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <iostream>
#include <sstream>
using namespace boost::archive;
std::stringstream ss;
class animal
{
public:
animal() = default;
animal(int legs) : legs_{legs} {}
int legs() const { return legs_; }
private:
friend class boost::serialization::access;
template <typename Archive>
void serialize(Archive &ar, const unsigned int version) { ar & legs_; }
int legs_;
};
void save()
{
text_oarchive oa{ss};
animal a{4};
animal &r = a;
oa << r;
}
void load()
{
text_iarchive ia{ss};
animal a;
animal &r = a;
ia >> r;
std::cout << r.legs() << '\n';
}
int main()
{
save();
load();
}
引用 r 的序列化等同于对象 a 的序列化。加载时,ia >> r 会将数据填充到 load 函数中新创建的本地对象 a 中。这种方式适用于不需要转移所有权,仅需持久化对象状态的场景。
总结与排错建议
在进行 C++ Boost Serialization 开发时,需注意以下几点:
- 内存管理:若使用原始指针,务必在序列化结束后检查是否需要在加载侧清理内存,尽管示例中展示了显式
delete,但在复杂架构中建议使用智能指针包裹以保安全。 - C++11 兼容性:如需使用
std::shared_ptr,请确认所用 Boost 版本是否已整合对标准库智能指针的支持,否则需回退至boost::shared_ptr或编写自定义适配器。 - 版本控制:在类中实现序列化接口时,注意
serialize函数签名中的version参数,以便在未来修改数据结构时保持向后兼容。
以上就是 C++ Boost Serialization 库指针与引用序列化详细内容的解答,更多关于 C++ 数据存储与格式化的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









