boost::序列化和循环引用反序列化
boost::serialization and cyclic reference deserialization
我有一个树状结构需要序列化。典型结构,每个节点具有parent
成员和children
向量。 parent
是指向类的原始指针,children
是shared_ptr
vector
。现在看来序列化工作正常,但反序列化使parent
成员未初始化(指向0xcccccccc
或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
,parent
会正确填充。
更新2:好的,我已经设法将其转换为显示问题的最小示例。应编译以下内容:
#include <boostarchivebinary_oarchive.hpp>
#include <boostarchivebinary_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;
}
单步执行代码。孩子的parent
始终保持为空。
好吧,显然我成了另一个倒霉虫的牺牲品。根据最新的Boost发布页面,Boost 1.55还没有针对VS2013的工作序列化库。谈论浪费的时间...
VisualStudio 2013/Visual C++ 12 的已知错误
Visual Studio 2013 在发布过程中发布得很晚,所以存在几个 未解决的问题。其中包括:
由于缺少包含,序列化无法编译。
我过去也有同样的问题,我没有从开箱即用中找到可靠的解决方案......但是下面的小技巧工作正常 - 您可以分别指定序列化和反序列化函数(不使用默认模板和 &-运算符(:
//! 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;
}
此问题已在开发分支上解决。
请参阅 https://svn.boost.org/trac/boost/ticket/9601
如果您使用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;
}
}
(我假设您在构造函数中将"父"设置为 NULL(。
我没有用VS 2013测试这段代码。
- 如何知道QDataStream不能反序列化某些内容
- 增强基于 XML class_id的反序列化
- 提升反序列化对象具有 nan 或 -nan 值
- 如何在 c++ 非托管代码中反序列化 byte[] 的 json 字符串?
- 如何反序列化数组?
- Protobuf中重复字段的问题.使用重复字段进行序列化/反序列化的更好方法是什么?
- 通过 tcp 发送 C# 类并在 C++ 上反序列化
- 序列化和反序列化boost共享指针
- 在C++中使用POCO和grain对多个对象进行反序列化
- C++中整数向量的序列化/反序列化
- 使用 Json 转换器反序列化 WCF 服务中的C++字符串
- 使用 QDataStream 对原始数据进行反序列化
- 使用协议缓冲区创建通用反序列化程序
- 如何在C++中从头开始反序列化文件(没有库)
- 在协议缓冲区 c++ 中反序列化字符串数组
- 在进程的内存中序列化/反序列化
- 谷物/C++ 11 - 如何指定反序列化的可选参数
- 是否可以反序列化(从原始内存块)没有默认构造函数的对象?
- 如何从平面缓冲区中反序列化联合结构的 void* 值的大小
- boost::序列化和循环引用反序列化