boost :: serialization和循环引用反序列化

时间:2013-11-25 00:48:11

标签: c++ serialization boost c++11

我有一个需要序列化的树状结构。典型结构,每个节点都有parent个成员和children个向量。 parent是指向类的原始指针,childrenvector的{​​{1}}。现在看来序列化工作正常,但 de -serialization使shared_ptr成员未初始化(指向parent0xcccccccc)。

当实际父对象尚未完成反序列化时,正在加载0x00000000成员,即通过父parent的反序列化请求加载子parent成员。由于这是循环的,我想知道我是否需要采取特殊措施才能发挥作用。

感谢您的帮助。

更新:这是我的序列化功能的样子:

children

如果我发表评论template <typename Archive> void serialize(Archive& archive, GameCore::GameObject& t, const unsigned int version) { archive & boost::serialization::base_object<GameCore::Object>(t); archive & boost::serialization::base_object<GameCore::Updatable>(t); archive & t.parent; archive & t.transform; archive & t.components; archive & t.children; } archive & t.children会正确填充。

更新2:好的,我已成功将其转变为显示问题的最小样本。以下应编译:

parent

逐步完成代码。孩子的#include <boost\archive\binary_oarchive.hpp> #include <boost\archive\binary_iarchive.hpp> #include <fstream> #include <memory> #include <vector> class A { public: A() {} A(const A& rhs) = delete; int someInt = 0; A* parent = nullptr; std::vector<A*> children; template <class Archive> void serialize(Archive& archive, const unsigned int version) { archive & someInt; archive & parent; int count = children.size(); archive & count; children.resize(count); for (int i = 0; i < count; ++i) { A* ptr = children[i]; archive & ptr; children[i] = ptr; } } }; int main() { A* newA = new A(); newA->someInt = 0; A* newPtr = new A(); newPtr->someInt = 5; newPtr->parent = newA; newA->children.push_back(newPtr); // Save. std::ofstream outputFile("test", std::fstream::out | std::fstream::binary); if (outputFile.is_open()) { boost::archive::binary_oarchive outputArchive(outputFile); // Serialize objects. outputArchive << newA; outputFile.close(); } delete newA; delete newPtr; A* loadedPtr = nullptr; // Load. std::ifstream inputFile("test", std::fstream::binary | std::fstream::in); if (inputFile && inputFile.good() && inputFile.is_open()) { boost::archive::binary_iarchive inputArchive(inputFile); // Load objects. inputArchive >> loadedPtr; inputFile.close(); } return 0; } 始终为空。

4 个答案:

答案 0 :(得分:3)

好吧,显然我成了另一个不幸的小虫的牺牲品。根据{{​​3}},Boost 1.55还没有VS2013的工作序列化库。 谈论浪费时间......

  

Visual Studio 2013 / Visual C ++ 12的已知错误

     

Visual Studio 2013   在发布过程中很晚才发布,所以存在几个   尚未解决的问题。其中包括:

     

由于缺少include,序列化无法编译。

答案 1 :(得分:1)

我过去遇到了同样的问题,我没有找到开箱即用的可靠解决方案..但是下面的小黑客工作正常 - 你可以单独指定序列化和反序列化功能(不使用默认值)模板和&amp; -operator):

//! Serialization
void A::serialize(xml_oarchive& ar, const unsigned int version)
{
   ar << value;
}
//! De-serialization
void A::serialize(xml_iarchive& ar, const unsigned int version)
{
   ar >> value;
}

之后,您可以指定在反序列化方法中恢复指向父对象的指针,如下所示:

//! Serialization
void A::serialize(xml_oarchive& ar, const unsigned int version)
{
   ar << children;
}
//! De-serialization
void A::serialize(xml_iarchive& ar, const unsigned int version)
{
   ar >> children;
   for(var child: children)
       child->parent = this;
}

答案 2 :(得分:1)

这已在开发分支上解决。

请参阅。 https://svn.boost.org/trac/boost/ticket/9601

答案 3 :(得分:0)

如果你使用Boost Serialization,一切都应该是开箱即用的。您的类序列化可能看起来像

#include <boost/serialization/vector.hpp>
void serialize (Archive&ar, unsigned int version)
{
     //declare possible derived types of nodes
     ar & parent;
     ar & children;
}

归档将散列指针,因此它不会多次创建每个元素。

一个重要的细节:如果您的节点可以是某种派生类型,您需要教导存档在//位置期望的类型, 通过指向基类型的指针,查看有关序列化派生类型的boost文档中的详细信息。

如果你确定你的树结构是正确的并且是自包含的(root有NULL作为父对象,所有其他节点都是它们各自“父”的“子”等),那么你可以更有效地组织代码:

#include <boost/serialization/vector.hpp>
void serialize (Archive&ar, unsigned int version)
{
     //declare possible derived types of nodes (either here or at archive creation point)        
     ar & children;
     if (typename Archive::is_loading())
     {
          for (auto child : children)
             child->parent = this;
     }
}

(我假设你在构造函数中将“parent”设置为NULL)。

我没有使用VS 2013测试此代码。