我是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 *。
特别是通过反序列化会出现问题(指针!)。有人有想法吗?
答案 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实例的非循环引用不应该有任何问题。