C++ 序列化和循环引用反序列化

C++ 序列化和循环引用反序列化,c++,serialization,boost,c++11,C++,Serialization,Boost,C++11,我有一个需要序列化的树状结构。典型结构,每个节点都有父节点成员和子节点向量parent是指向类的原始指针,children是shared_ptrs的vectors。现在看来,序列化工作正常,但反序列化会使父成员未初始化(指向0xcccc或0x00000000) 当实际的父对象尚未完成反序列化时,将加载父对象的成员,即,通过父对象的子对象的反序列化请求加载子对象的父对象的成员。由于这是周期性的,我想知道是否需要采取特殊措施使其工作 谢谢你的帮助 更新:这就是我的序列化函数的外观: template

我有一个需要序列化的树状结构。典型结构,每个节点都有
父节点
成员和
子节点
向量
parent
是指向类的原始指针,
children
shared_ptr
s的
vector
s。现在看来,序列化工作正常,但反序列化会使
父成员未初始化(指向
0xcccc
0x00000000

当实际的父对象尚未完成反序列化时,将加载父对象的
成员,即,通过父对象的
子对象的反序列化请求加载子对象的
父对象的
成员。由于这是周期性的,我想知道是否需要采取特殊措施使其工作

谢谢你的帮助

更新:这就是我的序列化函数的外观:

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;
}

逐步完成代码。子对象的父对象始终保持为空。

如果使用Boost序列化,则所有操作都应开箱即用。您可以将类序列化为

#include <boost/serialization/vector.hpp>
void serialize (Archive&ar, unsigned int version)
{
     //declare possible derived types of nodes
     ar & parent;
     ar & children;
}
#包括
无效序列化(存档和ar,未签名整数版本)
{
//声明节点的可能派生类型
应收账款及母公司;
ar&children;
}
存档将散列指针,因此不会多次创建每个元素

一个重要的细节是:如果您的节点可以是某种派生类型,那么您需要在//place教授归档所需的类型, 请参阅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;
     }
}
#包括
无效序列化(存档和ar,未签名整数版本)
{
//声明可能的节点派生类型(在此处或存档创建点)
ar&children;
if(typename存档::正在加载()
{
用于(自动子对象:子对象)
子->父=此;
}
}
(我假设您在构造函数中将“parent”设置为NULL)


我没有用VS 2013测试这段代码。

好吧,显然我被另一个不幸的错误所害。据《每日邮报》报道,Boost 1.55还没有一个适用于VS2013的序列化库。 谈论浪费的时间

使用Visual Studio 2013/Visual C++ 12

的已知错误 Visual Studio 2013 在发布过程中发布得比较晚,因此存在几个 未解决的问题。这些措施包括:

由于缺少包含,序列化无法编译


我过去也遇到过同样的问题,我没有从现成的产品中找到解决方案。。但是下面的小技巧很管用-您可以分别指定序列化和反序列化函数(不使用默认模板和&-运算符):

/!系列化
void A::serialize(xml\u oarchive&ar,const unsigned int版本)
{
ar>值;
}
然后,您可以在反序列化方法中指定还原指向父对象的指针,如下所示:

//! 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;
}
/!系列化
void A::serialize(xml\u oarchive&ar,const unsigned int版本)
{
ar>儿童;
for(变量子项:子项)
子->父=此;
}

这已在开发分支上解决


如果任何人,任何人都可以复制这个问题,请让我知道,因为它让我发疯!FWIW:更新2中的程序(加上一些验证的断言),所以问题就在你这边。那我到底做错了什么?我已经在两台机器上测试过了,两个不同的Boost版本。。。也许我建错了?我不知道你从哪里得到的信息。您是否可以引用/引用特定的文档位置,该位置告诉您VS2013没有序列化库?(我可以看到VC12还没有列在(附加的)测试编译器下,但那是另一回事)在我链接的页面顶部用引号更新了我的答案。你使用的是哪个版本的boost?我在x64上使用预构建的1.54进行了尝试,并且正确地填充了
parent
指针。顺便说一句,事实上我正在使用你的解决方法,但我也遇到了一个错误,指针首先被反序列化,然后在一个完全不同的地方反序列化(没有像这样简单的解决方法),第二个结果是null或未初始化。我想它是boost 1.33,但我不确定。顺便说一句,我已经在gcc(mingw64)上用1.54和1.55测试了您的代码,它工作正常。我还检查了boost序列化中的默认引用计数,它适用于树结构、双链接列表和循环列表-所有指向父元素的指针都已正确还原。是的,这是VC++12的问题。您不需要以这种方式拆分序列化,这不是boost建议的。首选的方法是让一个统一函数与
if(typename Archive::is_loading())
if(typename Archive::is_saving())
下的某些部分序列化(如有必要)。这样,“保存”和“加载”之间不一致的可能性最小。或者,您可以使用名为“save”和“load”的单独函数,然后使用Boost.Serialize宏Boost\u SERIALIZATION\u SPLIT\u FREE或Boost\u SERIALIZATION\u SPLIT\u MEMBER组合它们。
//! 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;
}