Boost 序列化:使用根内存管理序列化树
Boost Serialization: Serializing a tree with root memory management
我有一个自定义树数据结构,我决定采用以下设置。我有一个 Tree
class,带有向左、向右和向上(父级)的普通指针,然后我有一个继承自 Tree
的 Root
class ; root class 处理所有内存管理。 (树需要快,所以我买不起共享指针)。树中的每个节点都存在于根的内存池中(因此 left()
将指向内存池内部),每个指向某些 Data
:
的指针也是如此
class Root;
class Tree {
public:
inline Tree() : mLeft(nullptr), mRight(nullptr), mParent(nullptr),
mRoot(nullptr), mData(nullptr) {}
inline Tree *left() { return mLeft; }
inline Tree *right() { return mRight; }
inline Tree *parent() { return mParent; }
inline Root *root() { return mRoot; }
inline Data *data() { return mData; }
inline bool isLeaf() { return mData == nullptr; }
...
protected:
inline Tree(Tree *parent, Root *root) :
mLeft(nullptr), mRight(nullptr), mParent(parent), mRoot(root),
mData(nullptr) {}
Tree *mLeft;
Tree *mRight;
Tree *mParent;
Root *mRoot;
Data *mData;
};
class Root : public Tree {
friend class Tree;
public:
inline Root() : Tree(nullptr, this) {}
private:
MemoryPool<Data> mDataSpace; // behaves like std::set for the purposes of this example
MemoryPool<Tree> mNodeSpace;
};
Tree
class 使用其 mRoot
引用来分配新的子节点,例如,如果我想拆分一个节点。
我现在想序列化树。 Boost 提供了一个非常好的序列化库,但我不确定如何将它融入我当前的设置中。理想情况下我想写:
template<class Archive>
void serialize(Archive & ar, const unsigned int version) {
ar & mParent;
ar & mRoot;
if (!isLeaf()) {
left()->serialize(ar, version);
ar & mLeft;
ar & mRight;
ar & mData;
right()->serialize(ar, version);
}
}
我很确定这在保存时可以正常工作,但是加载呢?在成为其他节点的子节点之前,每个节点都需要在 mDataSpace
中分配。那么父节点呢?我不认为 Boost 的序列化足够聪明,可以在不先完成一些额外工作的情况下实现这些细节,对吗?
更复杂的是,结构 Data
是不可变的,我不能为它编写侵入式序列化。要序列化我可以使用 ar & data.x()
但要反序列化我需要写 data = Data(x);
.
我假设我必须为 Tree
编写某种特殊的构造函数,它在根节点的内存容器中为 Tree
成员分配一些 space [=25] =] 等等?
也许 Boost 序列化不是这里的理想选择?感谢您的指导或提示!
是的,您走对了。要让 Boost Serialization 实例化动态对象 (Node/Data),您将实现
save_construct_data
和
load_construct_data
您可以在 Data
类 的上下文中阅读此内容,它们不是 默认可构建的 :http://www.boost.org/doc/libs/1_59_0/libs/serialization/doc/serialization.html#constructors
现在,对于中央分配,您可以使用它。但是,我建议简单地序列化 mDataSpace
和 mNodeSpace
容器,并将索引序列化到它们中,而不是使用 boost 来序列化所有被跟踪的对象引用可能更容易。
因为 Boost Serialization 不必执行 Object Tracking,这会更容易且更有效。更重要的是,您只需要确保在任何节点之前序列化根,就可以了。
开箱即用:
跳出框框思考,我已经实现了完全相同的事情,但使用 Boost Intrusive 为我实际执行树算法。 Boost Intrusive 容器实际上并不拥有它们的元素,并且树根的表示方式与您在此处所做的方式几乎相同。因此,您可以拥有节点存储 + 侵入式容器的元组,并免费获得所有实现细节。
我有一个自定义树数据结构,我决定采用以下设置。我有一个 Tree
class,带有向左、向右和向上(父级)的普通指针,然后我有一个继承自 Tree
的 Root
class ; root class 处理所有内存管理。 (树需要快,所以我买不起共享指针)。树中的每个节点都存在于根的内存池中(因此 left()
将指向内存池内部),每个指向某些 Data
:
class Root;
class Tree {
public:
inline Tree() : mLeft(nullptr), mRight(nullptr), mParent(nullptr),
mRoot(nullptr), mData(nullptr) {}
inline Tree *left() { return mLeft; }
inline Tree *right() { return mRight; }
inline Tree *parent() { return mParent; }
inline Root *root() { return mRoot; }
inline Data *data() { return mData; }
inline bool isLeaf() { return mData == nullptr; }
...
protected:
inline Tree(Tree *parent, Root *root) :
mLeft(nullptr), mRight(nullptr), mParent(parent), mRoot(root),
mData(nullptr) {}
Tree *mLeft;
Tree *mRight;
Tree *mParent;
Root *mRoot;
Data *mData;
};
class Root : public Tree {
friend class Tree;
public:
inline Root() : Tree(nullptr, this) {}
private:
MemoryPool<Data> mDataSpace; // behaves like std::set for the purposes of this example
MemoryPool<Tree> mNodeSpace;
};
Tree
class 使用其 mRoot
引用来分配新的子节点,例如,如果我想拆分一个节点。
我现在想序列化树。 Boost 提供了一个非常好的序列化库,但我不确定如何将它融入我当前的设置中。理想情况下我想写:
template<class Archive>
void serialize(Archive & ar, const unsigned int version) {
ar & mParent;
ar & mRoot;
if (!isLeaf()) {
left()->serialize(ar, version);
ar & mLeft;
ar & mRight;
ar & mData;
right()->serialize(ar, version);
}
}
我很确定这在保存时可以正常工作,但是加载呢?在成为其他节点的子节点之前,每个节点都需要在 mDataSpace
中分配。那么父节点呢?我不认为 Boost 的序列化足够聪明,可以在不先完成一些额外工作的情况下实现这些细节,对吗?
更复杂的是,结构 Data
是不可变的,我不能为它编写侵入式序列化。要序列化我可以使用 ar & data.x()
但要反序列化我需要写 data = Data(x);
.
我假设我必须为 Tree
编写某种特殊的构造函数,它在根节点的内存容器中为 Tree
成员分配一些 space [=25] =] 等等?
也许 Boost 序列化不是这里的理想选择?感谢您的指导或提示!
是的,您走对了。要让 Boost Serialization 实例化动态对象 (Node/Data),您将实现
save_construct_data
和load_construct_data
您可以在 Data
类 的上下文中阅读此内容,它们不是 默认可构建的 :http://www.boost.org/doc/libs/1_59_0/libs/serialization/doc/serialization.html#constructors
现在,对于中央分配,您可以使用它。但是,我建议简单地序列化 mDataSpace
和 mNodeSpace
容器,并将索引序列化到它们中,而不是使用 boost 来序列化所有被跟踪的对象引用可能更容易。
因为 Boost Serialization 不必执行 Object Tracking,这会更容易且更有效。更重要的是,您只需要确保在任何节点之前序列化根,就可以了。
开箱即用:
跳出框框思考,我已经实现了完全相同的事情,但使用 Boost Intrusive 为我实际执行树算法。 Boost Intrusive 容器实际上并不拥有它们的元素,并且树根的表示方式与您在此处所做的方式几乎相同。因此,您可以拥有节点存储 + 侵入式容器的元组,并免费获得所有实现细节。