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

c++ boost serialization class refer to each other

本文关键字:引用 之间 boost 序列化 c++      更新时间:2023-10-16

我是c++ boost的新手,所以这个问题可能是基本的:如何序列化两个用指针相互引用的类。例如:

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*的私有列表。

特别是通过反序列化会有问题(指针!)。有人知道吗?

由于对象跟踪,序列化可以很好地处理指针的循环引用。如果通过指针序列化对象,则默认使用对象跟踪。它还附带了std::vector的序列化器(包括boost/serialization/vector.hpp)。

提振。序列化将跟踪您序列化的对象的地址。如果遇到一个已经序列化的地址,它将存储一个对该对象的"引用",而不是再次序列化它。

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

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

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(在其vector中)时首先作为指针遇到。序列化b本身时,只存储对b的引用。

A a;
B b;
archive >> a >> b; // crashes when deserializing b!

当反序列化a时,将在vector中分配b。现在您想要恢复b,它已经存在于堆栈中。因为你不能给堆栈上的变量赋一个新地址,它会崩溃!

正确的:

A* a = new A();
B* b = new B();
a.vec.push_back(b); // OK! this works fine

当对b进行反序列化时,boost只会将a向量内的b的地址赋值给它。

提振。序列化还附带了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向量(只包括头部),则不需要更改

基本思想是避免循环引用,因为您的序列化将产生一个无限循环。

根据本教程,A和B实例之间的非循环引用不应该有任何问题