【问题标题】:Boost serialization and pointers to parent class提升序列化和指向父类的指针
【发布时间】:2017-09-11 15:05:36
【问题描述】:

假设以下简化代码:

父类

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

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

子类中的指针是否会正确恢复,从而保证指向它的父类?

这似乎可以工作,我通过调试器单步执行并将父级的 this 指针的值与子级的 m_parent 进行比较来验证这一点。但是,我无法弄清楚 boost 是如何实现这一点的,这让我想知道我是否只是“走运”。任何人都可以验证 boost 序列化是否足够聪明以维护 child::m_parent->parent 关系?

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

【问题讨论】:

  • 对不起,错字,应该是:Parent * m_parent{nullptr};

标签: serialization boost


【解决方案1】:

两件事:

  • Object Tracking 促进了这一点。序列化指针时默认启用对象跟踪。

  • 不,你不要像那样序列化unique_ptr。

事实上,也没有什么理由序列化子代的m_parent,因为父代可以在负载处理程序中设置自引用。

但是假设您想要简单的方法,让我们坚持这个想法并通过对象跟踪使其工作

演示

我包含了一些技巧来演示反序列化

  • 正确重复删除指向同一对象的指针
  • 即使我们在反序列化之前强行“破坏”不变量,也会恢复成员指针

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-19
    • 2018-12-22
    • 1970-01-01
    • 1970-01-01
    • 2018-12-13
    • 2015-10-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多