如何使用boost :: serialization?序列化/反序列化此类?
#include <vector>
struct Foo {
struct Bar {
std::vector<int> * data; // Must point to Foo::data
Bar( std::vector<int> * d ) : data(d) { }
};
std::vector<int> data;
std::vector<Bar> elements;
Foo() {
// do very time consuming calculation to populate "data" and "elements"
}
};
当从序列化数据加载对象时,不得执行Foo中的构造函数,但如果对象是默认构造的,则必须对构造函数进行求值。
可以向Bar添加默认构造函数,但在序列化之后,Foo :: Bar :: data必须指向Foo :: data。
编辑:以下是我尝试的非工作实施
这是我基于@Matthieu提示的尝试。问题是,当我反序列化Foo时,我在Foo :: data和Foo :: elements中没有得到任何元素。
struct Foo {
struct Bar {
std::vector<int> * data;
Bar( ) : data( 0 ) { }
Bar( std::vector<int> * d ) : data(d) { }
template<class Archive>
void serialize(Archive & ar, const unsigned int version) {
ar & data;
}
};
std::vector<int> data;
std::vector<Bar> elements;
Foo() {
std::cerr << "Running default constructor" << std::endl;
data.push_back(1);
data.push_back(2);
data.push_back(3);
data.push_back(4);
data.push_back(5);
elements.push_back( Bar( &data ) );
elements.push_back( Bar( &data ) );
elements.push_back( Bar( &data ) );
}
template<class Archive>
Foo( Archive & ar ) {
ar >> data; // is this corrent?
ar >> elements;
}
private:
BOOST_SERIALIZATION_SPLIT_MEMBER();
friend class boost::serialization::access;
template<class Archive>
void save(Archive & ar, const unsigned int version) const {
const std::vector<int> * data_ptr = &data;
// should data be seriliazed as pointer...
// it is used as a pointer in Bar
ar << data_ptr;
ar << elements;
}
};
int main(int argc, const char *argv[])
{
#if 0
// serialize
Foo foo;
boost::archive::text_oarchive oar(std::cout);
oar << foo;
#else
// deserialize
boost::archive::text_iarchive oar(std::cin);
Foo foo(oar);
#endif
std::cerr << foo.data.size() << std::endl;
std::cerr << foo.elements.size() << std::endl;
std::cerr << (&foo.data) << std::endl;
for( const auto& a : foo.data )
std::cerr << a << " ";
std::cerr << std::endl;
for( const auto& a : foo.elements)
std::cerr << a.data << " ";
std::cerr << std::endl;
return 0;
}
答案 0 :(得分:2)
文档中有一节描述如何使用非默认构造函数(de)序列化类。请参阅here。
基本上,您必须在命名空间save_construct_data
中实现名为load_construct_data
和boost::serialization
的两个函数来写出并读入用于构造类实例的数据。然后,您可以使用重建Foo
对象所需的参数从load_construct_data
函数调用Foo
的非默认构造函数。
以下是基于更新代码的工作示例:
请注意,我使用shared_ptr
来澄清由Foo和Bar序列化的data
成员引用相同的内容。
#include <vector>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/scoped_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <iostream>
#include <sstream>
struct Foo {
struct Bar {
boost::shared_ptr< std::vector<int> > data; // Must point to Foo::data
Bar( boost::shared_ptr< std::vector<int> > d ) : data(d) { }
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
// ** note that this is empty **
}
};
boost::shared_ptr< std::vector<int> > data;
std::vector<Bar> elements;
Foo() : data( new std::vector<int>() ) {
std::cerr << "Running default constructor" << std::endl;
data->push_back(1);
data->push_back(2);
data->push_back(3);
data->push_back(4);
data->push_back(5);
elements.push_back( Bar( data ) );
elements.push_back( Bar( data ) );
elements.push_back( Bar( data ) );
}
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
// ** note that this is empty **
}
Foo(
boost::shared_ptr< std::vector<int> > const & data_,
std::vector<Bar> const & elements_ ) : data( data_ ), elements( elements_ )
{
std::cout << "cheap construction" << std::endl;
}
};
namespace boost { namespace serialization {
template<class Archive>
inline void save_construct_data(
Archive & ar, const Foo * foo, const unsigned int file_version
){
ar << foo->data << foo->elements;
}
template<class Archive>
inline void load_construct_data(
Archive & ar, Foo * foo, const unsigned int file_version
){
boost::shared_ptr< std::vector<int> > data;
std::vector<Foo::Bar> elements;
ar >> data >> elements;
::new(foo)Foo(data, elements);
}
template<class Archive>
inline void save_construct_data(
Archive & ar, const Foo::Bar * bar, const unsigned int file_version
){
ar << bar->data;
}
template<class Archive>
inline void load_construct_data(
Archive & ar, Foo::Bar * bar, const unsigned int file_version
){
boost::shared_ptr< std::vector<int> > data;
ar >> data;
::new(bar)Foo::Bar(data);
}
}}
int main()
{
std::stringstream ss;
{
boost::scoped_ptr< Foo > foo( new Foo() );
std::cout << "size before serialization is: " << foo->data->size() << std::endl;
boost::archive::text_oarchive oa(ss);
oa << foo;
}
{
boost::scoped_ptr< Foo > foo;
boost::archive::text_iarchive is(ss);
is >> foo;
std::cout << "size after deserialization is: " << foo->data->size() << std::endl;
}
return 0;
}