Boost.Serialization 可以很好地处理指针的循环引用,这要感谢object tracking。
如果通过指针序列化对象,则默认使用对象跟踪。它还带有std::vector 的序列化程序(包括boost/serialization/vector.hpp)。
Boost.Serialzation 将跟踪您序列化的对象的地址。
如果它遇到一个已经序列化的地址,它将存储一个对对象的“引用”而不是再次序列化它。
在反序列化时,它会在遇到这些引用时将它们解析为正确的地址(这意味着它们必须是指针,以便可以将地址分配给它们)。
唯一的限制是,引用的对象必须动态分配(在堆上)。你可以序列化堆栈上的一个对象,只要它没有被另一个对象引用。
A a;
B b;
a.vec.push_back( &b ); // WRONG! deserialization will crash
// if a does not reference to b, it will work
archive << a << b;
原因是:b 在序列化 a(在其向量中)时首先作为指针遇到。序列化 b 本身时,只存储对 b 的引用。
A a;
B b;
archive >> a >> b; // crashes when deserializing b!
在反序列化a时,b会被分配到vector中。现在你想恢复堆栈中已经存在的 b 。由于不能给栈上的变量分配新地址,所以会崩溃!
正确:
A* a = new A();
B* b = new B();
a.vec.push_back(b); // OK! this works fine
当反序列化b时,boost会简单的将a的向量内的b的地址分配给它。
Boost.Serialzation 还附带了一个用于boost::shared_ptr(包括boost/serialization/shared_ptr.hpp)的序列化程序,它可以通过以下方式使您的任务更加轻松
改为使用std::vector< boost::shared_ptr<A> >,这样您就不必担心释放内存。
有了基础知识,您就可以像这样简单地实现类的序列化:
// add this to your classes you want to serialize
private:
friend boost::serialization::access;
template<class Archive>
void serialize(Archive& ar, unsigned version) {
//TODO: serialize other member variables
ar & BOOST_SERIALIZATION_NVP(vec); // vec is a std::vector
}
如果您选择使用 shared_ptrs 的向量(仅包含标题),则无需更改。