C++ Boost 序列化、构造函数和数据复制

Posted

技术标签:

【中文标题】C++ Boost 序列化、构造函数和数据复制【英文标题】:C++ Boost serialization, constructor and data copying 【发布时间】:2017-01-13 21:57:33 【问题描述】:

我试图了解 boost 库的序列化是如何工作的,我只想确保我的想法是正确的。

如果我保存对象(我只有指向该对象的指针)然后尝试加载它,则顺序如下:

    调用此对象的构造函数。 复制数据。

问题是如果构造函数使用类的静态成员(例如一些计数器),它会给我关于加载对象的误导信息。我有基于静态计数器的对象 ID,并且(加载后)构造函数打印到控制台的对象 ID 不正确。这似乎对我的程序没有任何伤害,因为在调用构造函数后一切正常。甚至析构函数也会打印出正确的对象 ID。

我对这个序列是否正确?或者也许这里正在发生其他一些“魔法”?

【问题讨论】:

你是否序列化和反序列化对象的 ID? 可以,但是构造函数打印的ID不正确。调用构造函数后,ID似乎加载正确 如果我序列化多个对象,所有 ID(第一个对象除外)都相同(计数器已加载?)。这一切都让我觉得调用构造函数后数据正在加载,这很合理。 【参考方案1】:

如果我保存对象(我只有指向该对象的指针)然后尝试加载它,> 顺序如下:

    调用此对象的构造函数。 复制数据。

你是对的。 boost序列化库加载数据时,首先调用默认构造函数,然后复制数据,只要你使用serialize()成员函数模板即可。

这是一个例子。还可以看到执行结果:http://melpon.org/wandbox/permlink/xlzdnK0UnZo48Ms2

#include <fstream>
#include <string>
#include <cassert>
#include <iostream>

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

class Person 
public:
    Person():id_(id_master_++) 
        std::cout << "Person() id = " << id_ << " and id_master_ is incremented to " << id_master_ <<std::endl;
    ;
    ~Person() 
        std::cout << "~Person() id = " << id_ << std::endl;
    
    Person(std::string const& name, int age)
        :id_(id_master_++),
         name_(name), 
         age_(age) 
        std::cout << "Person(std::string const&, int) id = " << id_ << " and id_master_ is incremented to " << id_master_ <<std::endl;
    
    std::string const& name() const  return name_; 
    int age() const  return age_; 
private:
    static int id_master_;
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, unsigned int /*version*/)
    
        ar & name_;
        ar & age_;
        std::cout << "before store or load id = " << id_ << std::endl;
        ar & id_; // *1
        std::cout << "after store or load id = " << id_ << std::endl;
    
    int id_;
    std::string name_;
    int age_;
;

int Person::id_master_;

int main()

    
        Person p1("John", 25);
        std::ofstream ofs("person.txt");
        boost::archive::text_oarchive oa(ofs);
        oa << p1;
    
    
        std::ifstream ifs("person.txt");
        boost::archive::text_iarchive ia(ifs);
        Person p2;
        ia >> p2;
        assert(p2.name() == "John");
        assert(p2.age() == 25);
    

对象的 id 被 *1 处加载的数据覆盖。

这似乎对我的程序没有任何伤害,因为调用构造函数后一切正常。

有害或无害取决于您的情况。对象按您的预期反序列化,但在我的示例中,id_master_ 递增到 2。小心这种行为。

【讨论】:

以上是关于C++ Boost 序列化、构造函数和数据复制的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 boost/python 向 python 公开 C++ 虚函数?

boost.variant 派生类型:不能使用复制构造函数

如何使用 boost_python 将 C++ 序列化数据公开给 python

C++ 从类的构造函数运行 boost 线程

boost::variant 中持有的类的复制构造函数的问题

C++ 中的 boost::scoped_ptr 和 STL