Boost.Serialization 将很好地处理指针的循环引用,这要归功于对象跟踪。如果通过指针序列化对象,则默认使用对象跟踪。它还带有一个用于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;
这样做的原因是:在序列化a(在其向量中)时,首先遇到b作为指针。当序列化b本身时,只存储对b的引用。
A a;
B b;
archive >> a >> b; // crashes when deserializing b!
反序列化a时,b将分配在向量中。现在您要恢复堆栈中已经存在的b 。由于您无法为堆栈上的变量分配新地址,因此它将崩溃!
正确的:
A* a = new A();
B* b = new B();
a.vec.push_back(b); // OK! this works fine
当反序列化b时,boost 将简单地将b在 a 的向量中的地址分配给它。
Boost.Serialzation 还附带了一个用于boost::shared_ptr
(include 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 的向量(仅包括标题),则无需进行任何更改。