C++ Boost 序列化、构造函数和数据复制
C++ Boost serialization, constructor and data copying
我正在尝试了解 boost 库的序列化是如何工作的,我只想确保我的想法是正确的。
如果我保存对象(我只有指向这个对象的指针)然后尝试加载它,顺序如下:
- 正在调用此对象的构造函数。
- 正在复制数据。
问题是,如果构造函数使用 class 的静态成员(例如一些计数器),它会给我关于加载对象的误导性信息。我有基于静态计数器的对象 ID,并且(加载后)构造函数打印到控制台的对象 ID 不正确。它似乎对我的程序没有任何危害,因为在调用构造函数之后一切正常。甚至析构函数也打印出正确的对象 ID。
我对这个序列的看法是否正确?或者这里可能发生了其他 "magic"?
If I save object (I have only pointer to this object) and then try to load it, > the sequence is following:
- Calling the constructor of this object.
- Copying the data.
你是对的。 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 处加载的数据覆盖。
It seems to make no harm to my program, because after calling constructor all works great.
有害与否取决于您的情况。对象按照您的预期反序列化,但在我的示例中,id_master_ 递增到 2。请注意该行为。
我正在尝试了解 boost 库的序列化是如何工作的,我只想确保我的想法是正确的。
如果我保存对象(我只有指向这个对象的指针)然后尝试加载它,顺序如下:
- 正在调用此对象的构造函数。
- 正在复制数据。
问题是,如果构造函数使用 class 的静态成员(例如一些计数器),它会给我关于加载对象的误导性信息。我有基于静态计数器的对象 ID,并且(加载后)构造函数打印到控制台的对象 ID 不正确。它似乎对我的程序没有任何危害,因为在调用构造函数之后一切正常。甚至析构函数也打印出正确的对象 ID。
我对这个序列的看法是否正确?或者这里可能发生了其他 "magic"?
If I save object (I have only pointer to this object) and then try to load it, > the sequence is following:
- Calling the constructor of this object.
- Copying the data.
你是对的。 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 处加载的数据覆盖。
It seems to make no harm to my program, because after calling constructor all works great.
有害与否取决于您的情况。对象按照您的预期反序列化,但在我的示例中,id_master_ 递增到 2。请注意该行为。