• boost serialization


    Archive

    An archive is a sequence of bytes that represented serialized C++ objects. Objects can be added to an archive to serialize them and then later loaded from the archive.

    1. boost::archive::text_iarchive

    #include <boost/archive/text_oarchive.hpp>
    #include <boost/archive/text_iarchive.hpp>
    #include <iostream>
    #include <fstream>
    
    using namespace boost::archive;
    
    void save()
    {
      std::ofstream file("archive.txt");
      text_oarchive oa{file};
      int i = 1;
      oa << i;
    }
    
    void load()
    {
      std::ifstream file("archive.txt");
      text_iarchive ia{file};
      int i = 0;
      ia >> i;
      std::cout << i << std::endl;
    }
    
    int main()
    {
      save();
      load();
      return 0;
    }

    The class boost::archive::text_oarchive serializes data as a text stream, and the class boost::archive::text_iarchive restores data from such a text stream. Constructors of archives expect an input or output stream as a parameter. The stream is used to serialize or restore data.

    2. serializing with a stringstream

    #include <boost/archive/text_oarchive.hpp>
    #include <boost/archive/text_iarchive.hpp>
    #include <iostream>
    #include <sstream>
    
    using namespace boost::archive;
    
    std::stringstream ss;
    
    void save()
    {
      text_oarchive oa{ss};
      int i = 1;
      oa << i;
    }
    
    void load()
    {
      text_iarchive ia{ss};
      int i = 0;
      ia >> i;
      std::cout << i << std::endl;
    }
    
    int main()
    {
      save();
      load();
      return 0;
    }

    output: 1

    3. user-defined types with a member function

    #include <boost/archive/text_oarchive.hpp>
    #include <boost/archive/text_iarchive.hpp>
    #include <iostream>
    #include <sstream>
    
    using namespace boost::archive;
    
    std::stringstream ss;
    
    class animal
    {
    public:
      animal() = default;
      animal(int legs) : legs_(legs) {}
      int legs() const { return legs_; }
    
    private:
      friend class boost::serialization::access;
    
      template <typename Archive>
      void serialize(Archive &ar, const unsigned int version) { ar & legs_; }
    
      int legs_;
    };
    
    void save()
    {
      text_oarchive oa(ss);
      animal a{4};
      oa << a;
    }
    
    void load()
    {
      text_iarchive ia(ss);
      animal a;
      ia >> a;
      std::cout << a.legs() << std::endl;
    }
    
    int main()
    {
      save();
      load();
      return 0;
    }

    In order to serialize objects of user-defined types, you must define the member function serialize(). This function is called when the object is serialized to or restored from a byte stream.

    serialize() is automatically called any time an object is serialized or restored.

    4. serializing with a free-standing function and serializing strings

    #include <boost/archive/text_oarchive.hpp>
    #include <boost/archive/text_iarchive.hpp>
    #include <boost/serialization/string.hpp>
    #include <iostream>
    #include <sstream>
    #include <string>
    #include <utility>
    
    using namespace boost::archive;
    
    std::stringstream ss;
    
    class animal
    {
    public:
      animal() = default;
      animal(int legs, std::string name) :
        legs_{legs}, name_{std::move(name)} {}
      int legs() const { return legs_; }
      const std::string &name() const { return name_; }
    
    private:
      friend class boost::serialization::access;
    
      template <typename Archive>
      friend void serialize(Archive &ar, animal &a, const unsigned int version);
    
      int legs_;
      std::string name_;
    };
    
    template <typename Archive>
    void serialize(Archive &ar, animal &a, const unsigned int version)
    {
      ar & a.legs_;
      ar & a.name_;
    }
    
    void save()
    {
      text_oarchive oa{ss};
      animal a{4, "cat"};
      oa << a;
    }
    
    void load()
    {
      text_iarchive ia{ss};
      animal a;
      ia >> a;
      std::cout << a.legs() << std::endl;
      std::cout << a.name() << std::endl;
    }
    
    int main()
    {
      save();
      load();
      return 0;
    }

    a member variable of type std::string, in order to serialize this member variable. the header file boost/serialization/string.hpp must be included to provide the appropriate free-standing function serialize().

    Pointers and References

    1. serializing pointers

    #include <boost/archive/text_oarchive.hpp>
    #include <boost/archive/text_iarchive.hpp>
    #include <iostream>
    #include <sstream>
    
    std::stringstream ss;
    
    class animal
    {
    public:
      animal() = default;
      animal(int legs) : legs_{legs} {}
      int legs() const { return legs_; }
    
    private:
      friend class boost::serialization::access;
    
      template <typename Archive>
      void serialize(Archive &ar, const unsigned int version) { ar & legs_; }
    
      int legs_;
    };
    
    void save()
    {
      boost::archive::text_oarchive oa(ss);
      animal *a = new animal(4);
      oa << a;
      std::cout << std::hex << a << std::endl;
      delete a;
    }
    
    void load()
    {
      boost::archive::text_iarchive ia(ss);
      animal *a;
      ia >> a;
      std::cout << std::hex << a << std::endl;
      std::cout << std::dec << a->legs() << std::endl;
      delete a;
    }
    
    int main()
    {
      save();
      load();
      return 0;
    }

    Boost.Serialization automatically serializes the object referenced by a and not the address of the object.

    If the archive is restored, a will not necessarily contain the same address. A new object is created and its address is assigned to a instead. Boost.Serialization only guarantees that the object is the same as the one serialized, not that its address is the same.

    2 serializing smart pointers

    #include <boost/archive/text_oarchive.hpp>
    #include <boost/archive/text_iarchive.hpp>
    #include <boost/serialization/scoped_ptr.hpp>
    #include <boost/scoped_ptr.hpp>
    #include <iostream>
    #include <sstream>
    
    using namespace boost::archive;
    
    std::stringstream ss;
    
    class animal
    {
    public:
      animal() = default;
      animal(int legs) : legs_(legs) {}
      int legs() const { return legs_; }
    
    private:
      friend class boost::serialization::access;
    
      template <typename Archive>
      void serialize(Archive &ar, const unsigned int version) { ar & legs_; }
    
      int legs_;
    };
    
    void save()
    {
      text_oarchive oa(ss);
      boost::scoped_ptr<animal> a(new animal(4));
      oa << a;
    }
    
    void load()
    {
      text_iarchive ia(ss);
      boost::scoped_ptr<animal> a;
      ia >> a;
      std::cout << a->legs() << std::endl;
    }
    
    int main()
    {
      save();
      load();
      return 0;
    }

    uses the smart pointer boost::scoped_ptr to manage a dynamically allocated object of type animal. Include the header file boost/serialization/scoped_ptr.hpp to serialize such a pointer. To serialize a smart pointer of type boost::shared_ptr, use the header file boost/serialization/shared_ptr.hpp.

    3. serializing references

    #include <boost/archive/text_oarchive.hpp>
    #include <boost/archive/text_iarchive.hpp>
    #include <iostream>
    #include <sstream>
    
    using namespace boost::archive;
    
    std::stringstream ss;
    
    class animal
    {
    public:
      animal() = default;
      animal(int legs) : legs_(legs) {}
      int legs() const { return legs_; }
    
    private:
      friend class boost::serialization::access;
    
      template <typename Archive>
      void serialize(Archive &ar, const unsigned int version) { ar & legs_; }
    
      int legs_;
    };
    
    void save()
    {
      text_oarchive oa(ss);
      animal a(4);
      animal &r = a;
      oa << r;
    }
    
    void load()
    {
      text_iarchive ia(ss);
      animal a;
      animal &r = a;
      ia >> r;
      std::cout << r.legs() << std::endl;
    }
    
    int main()
    {
      save();
      load();
    }

    Serialization of Class Hierarchy Objects

    Derived classes must access the function boost::serialization::base_object() inside the member function serialize() to serialize objects based on class hierarchies. This function guarantees that inherited member variables of base classes are correctly serialized.

    1. serializing derived classes correctly

    #include <boost/archive/text_oarchive.hpp>
    #include <boost/archive/text_iarchive.hpp>
    #include <iostream>
    #include <sstream>
    
    using namespace boost::archive;
    std::stringstream ss;
    
    class animal
    {
    public:
      animal() = default;
      animal(int legs) : legs_(legs) {}
      int legs() const { return legs_; }
    
    private:
      friend class boost::serialization::access;
    
      template <typename Archive>
      void serialize(Archive &ar, const unsigned int version) { ar & legs_; }
    
      int legs_;
    };
    
    class bird : public animal
    {
    public:
      bird() = default;
      bird(int legs, bool can_fly) :
        animal(legs), can_fly_{can_fly} {}
      bool can_fly() const { return can_fly_; }
    
    private:
      friend class boost::serialization::access;
    
      template <typename Archive>
      void serialize(Archive &ar, const unsigned int version)
      {
        ar & boost::serialization::base_object<animal>(*this);
        ar & can_fly_;
      }
    
      bool can_fly_;
    };
    
    void save()
    {
      text_oarchive oa(ss);
      bird penguin(2, false);
      oa << penguin;
    }
    
    void load()
    {
      text_iarchive ia(ss);
      bird penguin;
      ia >> penguin;
      std::cout << penguin.legs() << '
    ';
      std::cout << std::boolalpha << penguin.can_fly() << '
    ';
    }
    
    int main()
    {
      save();
      load();
      return 0;
    }

    Inherited member variables are serialized by accessing the base class inside the member function serialize() of the derived class and calling boost::serialization::base_object(). You must use this function rather than, for example, static_cast because only boost::serialization::base_object() ensures correct serialization

    2. registering derived classes statically with BOOST_CLASS_EXPORT

    #include <boost/archive/text_oarchive.hpp>
    #include <boost/archive/text_iarchive.hpp>
    #include <boost/serialization/export.hpp>
    #include <iostream>
    #include <sstream>
    
    using namespace boost::archive;
    
    std::stringstream ss;
    
    class animal
    {
    public:
      animal() = default;
      animal(int legs) : legs_(legs) {}
      virtual int legs() const { return legs_; }
      virtual ~animal() = default;
    
    private:
      friend class boost::serialization::access;
    
      template <typename Archive>
      void serialize(Archive &ar, const unsigned int version) { ar & legs_; }
    
      int legs_;
    };
    
    class bird : public animal
    {
    public:
      bird() = default;
      bird(int legs, bool can_fly) :
        animal{legs}, can_fly_(can_fly) {}
      bool can_fly() const { return can_fly_; }
    
    private:
      friend class boost::serialization::access;
    
      template <typename Archive>
      void serialize(Archive &ar, const unsigned int version)
      {
        ar & boost::serialization::base_object<animal>(*this);
        ar & can_fly_;
      }
    
      bool can_fly_;
    };
    
    BOOST_CLASS_EXPORT(bird)
    
    void save()
    {
      text_oarchive oa(ss);
      animal *a = new bird(2, false);
      oa << a;
      delete a;
    }
    
    void load()
    {
      text_iarchive ia(ss);
      animal *a;
      ia >> a;
      std::cout << a->legs() << '
    ';
      delete a;
    }
    
    int main()
    {
      save();
      load();
      return 0;
    }

    To have Boost.Serialization recognize that an object of type bird must be serialized, even though the pointer is of type animal*, the class bird needs to be declared. This is done using the macro BOOST_CLASS_EXPORT, which is defined in boost/serialization/export.hpp. Because the type bird does not appear in the pointer definition, Boost.Serialization cannot serialize an object of type bird correctly without the macro.

    The macro BOOST_CLASS_EXPORT must be used if objects of derived classes are to be serialized using a pointer to their corresponding base class. A disadvantage of BOOST_CLASS_EXPORT is that, because of static registration, classes can be registered that may not be used for serialization at all.

    3. register_type()

    #include <boost/archive/text_oarchive.hpp>
    #include <boost/archive/text_iarchive.hpp>
    #include <boost/serialization/export.hpp>
    #include <iostream>
    #include <sstream>
    
    std::stringstream ss;
    
    class animal
    {
    public:
      animal() = default;
      animal(int legs) : legs_(legs) {}
      virtual int legs() const { return legs_; }
      virtual ~animal() = default;
    
    private:
      friend class boost::serialization::access;
    
      template <typename Archive>
      void serialize(Archive &ar, const unsigned int version) { ar & legs_; }
    
      int legs_;
    };
    
    class bird : public animal
    {
    public:
      bird() = default;
      bird(int legs, bool can_fly) :
        animal{legs}, can_fly_(can_fly) {}
      bool can_fly() const { return can_fly_; }
    
    private:
      friend class boost::serialization::access;
    
      template <typename Archive>
      void serialize(Archive &ar, const unsigned int version)
      {
        ar & boost::serialization::base_object<animal>(*this);
        ar & can_fly_;
      }
    
      bool can_fly_;
    };
    
    void save()
    {
      boost::archive::text_oarchive oa(ss);
      oa.register_type<bird>();
      animal *a = new bird(2, false);
      oa << a;
      delete a;
    }
    
    void load()
    {
      boost::archive::text_iarchive ia(ss);
      ia.register_type<bird>();
      animal *a;
      ia >> a;
      std::cout << a->legs() << std::endl;
      delete a;
    }
    
    int main()
    {
      save();
      load();
      return 0;
    }

    The type to be registered is passed as a template parameter. Note that register_type() must be called both in save() and load().

    The advantage of register_type() is that only classes used for serialization must be registered. For example, when developing a library, one does not know which classes a developer may use for serialization later. While the macro BOOST_CLASS_EXPORT makes this easy, it may register types that are not going to be used for serialization.

  • 相关阅读:
    ES6中的类
    promise小案例
    Promise.resolve()与Promise
    Promise.resolve( data)与Promise.reject( data )
    Promise.race()
    Promise.all()
    咦?浏览器又崩了?再试试这个呢!
    页面太卡了?试试这方法呢!
    js进阶之重复的定时器
    关于vue+element-ui项目的分页,返回默认显示第一页的问题解决
  • 原文地址:https://www.cnblogs.com/sssblog/p/11347185.html
Copyright © 2020-2023  润新知