提升序列化和指向父类的指针

时间:2017-09-11 15:05:36

标签: serialization boost

假设以下简化代码:

家长班

    #include <boost/archive/text_oarchive.hpp>
    #include <boost/archive/text_iarchive.hpp>
    #include <boost/serialization/unique_ptr.hpp>

    class Parent
    {
    public:
        Parent();
        ...
    private:
        // boost serialization
        friend class boost::serialization::access;
        template<class Archive>
        void serialize(Archive & ar, const unsigned int version)
        {
            ar & *m_child;
        }

        std::unique_ptr<Child> m_child;
    }

    Parent::Parent()
    {
        ...
        m_child = std::unique_ptr<Child>(new Child(this));
    }

儿童课

    #include <boost/archive/text_oarchive.hpp>
    #include <boost/archive/text_iarchive.hpp>
    #include <boost/serialization/unique_ptr.hpp>

    class Child
    {
    public:
        Child(Parent * parent)
        {
            m_parent = parent;
        };
        ...
    private:
        // boost serialization
        friend class boost::serialization::access;
        template<class Archive>
        void serialize(Archive & ar, const unsigned int version)
        {
            ar & m_parent;
        }
        Child(){};

        Parent m_parent{ nullptr };
    }

我的父类创建一个子类,并将指针传递给子项存储的自身。 归档父类时,它会归档将指针归档到父级的子级。 恢复父类时,它会创建子类并恢复它。我的问题是:

子类中的指针是否会正确恢复,因此可以保证指向它的父级?

这个SEEMS可以通过逐步调试调试器并将Parent的this指针值与子节点的m_parent进行比较来验证。但是,我无法弄清楚助力如何将其拉下来,这让我想知道我是否只是“幸运”。任何人都可以验证boost序列化是否足够智能以维持child :: m_parent-&gt;父关系?

或者我应该采取额外的步骤:不加载指针并在加载对象后设置它?

1 个答案:

答案 0 :(得分:0)

两件事:

  • Object Tracking为此提供了便利。在序列化指针时,默认情况下启用对象跟踪。

  • 不,您没有像这样序列化unique_ptr

  

事实上,没有理由将序列化孩子的m_parent,因为父母可以在加载处理程序中设置自引用。 < / p>      

但是假设您想要简单的方法,让我们坚持这个想法并使其成为可能因为对象跟踪

样本

我提供了一些技巧来证明反序列化

  • 正确删除指向同一对象的指针
  • 恢复成员指针,即使我们有力地&#34;打破&#34;反序列化之前的不变量

<强> Live On Coliru

#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/unique_ptr.hpp>
#include <memory>
#include <sstream>
#include <iostream>

class Parent;

class Child {
  public:
    Child(Parent *parent) 
        : m_parent(parent), m_duplicate_parent(parent) {}

    Parent *m_parent          { nullptr };
    Parent *m_duplicate_parent{ nullptr };
  private:
    friend class boost::serialization::access;
    template <class Archive> void serialize(Archive &ar, unsigned) {
        ar & m_parent & m_duplicate_parent; 
    }

    Child() = default;
};

class Parent {
  public:
    Parent() : m_child(std::make_unique<Child>(this)) {}

  //private:
    friend class boost::serialization::access;
    template <class Archive> void serialize(Archive &ar, unsigned) {
        ar & m_child; 
    }

    std::unique_ptr<Child> m_child;
};

int main() {
    std::stringstream ss;
    {
        boost::archive::text_oarchive oa(ss);

        Parent p;
        assert(&p == p.m_child->m_parent);
        assert(&p == p.m_child->m_duplicate_parent);
        oa << p;
    }

    std::cout << ss.str();

    {
        boost::archive::text_iarchive ia(ss);

        Parent p;
        // let's purposelly break the invariants so we know deserialization
        // does restore them as required, and we not just "getting lucky":
        p.m_child->m_parent = nullptr;
        p.m_child->m_duplicate_parent = nullptr;
        assert(&p != p.m_child->m_parent);
        assert(&p != p.m_child->m_duplicate_parent);

        // nuclear:
        p.m_child.reset();

        // now deserialize
        ia >> p;

        assert(&p == p.m_child->m_parent);
        assert(&p == p.m_child->m_duplicate_parent);
    }
}

打印类似于

的内容
22 serialization::archive 15 1 0
0 0 0 2 1 0
1 0 0 0 0