c ++ boost序列化类互相引用

时间:2012-12-27 21:47:40

标签: c++ boost-serialization

我是C ++ boost的新手,所以这个问题可能是基本的: 如何序列化两个用指针引用的类。 e.g:

class A;
class B;

class A {
  public:
  ...
  private:
    double a;
    vector <B*> b;
}

class B {
  public:
  ...
  private:
    int b;
    list <A*> a;
}

类A的私有向量包含指针B *,而类B的私有列表包含A *。

特别是通过反序列化会出现问题(指针!)。有人有想法吗?

2 个答案:

答案 0 :(得分:3)

由于object tracking,Boost.Serialization将处理指针的循环引用。 如果通过指针序列化对象,则默认使用对象跟踪。它还附带std::vector的序列化程序(包括boost/serialization/vector.hpp)。

Boost.Serialzation将跟踪您序列化的对象的地址。 如果遇到已经序列化的地址,它将存储一个&#39;引用&#39;到对象而不是再次序列化。

反序列化时,它会在遇到它们时将这些引用解析为正确的地址(这意味着它们必须是指针,以便可以为它们分配地址)。

唯一的限制是,必须动态分配引用的对象(在堆上)。您可以序列化堆栈中的对象,只要它不被另一个对象引用。

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 将在向量中分配。现在你想恢复已经存在于堆栈中的 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向量(仅包含标题),则无需进行任何更改。

答案 1 :(得分:0)

基本思想是避免使用yclic引用,因为序列化会产生无限循环。

根据这个tutorial,A和B实例的非循环引用不应该有任何问题。