我最近在使用c++ Boost库进行序列化时遇到了一些非常令人困惑的问题。就我搜索而言,我找不到任何相关的信息。所以我在想也许有人能开导我…或者至少这将被引用,并可能在以后对任何人有用。
本质上:在c++中,使用Boost序列化库序列化对象不会产生相同的结果文件,如果您使用指针或使用值进行序列化。下面是复制它的代码片段
#include <string>
#include <fstream>
#include <boost/archive/text_oarchive.hpp> // boost::archive::text_oarchive
#include <boost/archive/text_iarchive.hpp> // boost::archive::text_iarchive
// we are getting into classics here
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)
{ if(version < 1)
{ ; }
ar & legs_;
}
int legs_;
} ;
// saves using pointer
void save_ptr(const std::string& path,
const animal* animal)
{
std::ofstream f_out(path) ;
boost::archive::text_oarchive arch_out(f_out) ;
arch_out << animal ;
f_out.close() ;
}
// save using value
void save_val(const std::string& path,
animal animal)
{
std::ofstream f_out(path) ;
boost::archive::text_oarchive arch_out(f_out) ;
arch_out << animal ;
f_out.close() ;
}
int main()
{
std::string path_out_val("val.animal") ;
std::string path_out_ptr("ptr.animal") ;
animal animal ;
save_val(path_out_val, animal) ;
save_ptr(path_out_ptr, &animal) ;
return 0 ;
}
在我的机器上,两个结果文件是不同的。
val.animal
22 serialization::archive 19 1 0
ptr.animal
22 serialization::archive 19 0 1 0
ptr中有一个额外的0。动物文件。
因此,如果您混合了值和指针序列化和反序列化,则在尝试从文件中重新加载数据时可能会遇到麻烦。这件事让我忙了好几天……
我想知道这是否有一个解释?或许我只是做错了什么?
是的。你做错了。
指针不是值。它们需要动态分配,需要对象跟踪。
(反)序列化所需的操作是值序列化的超集。从某种意义上说,T*
被序列化为*T
(如果不是nullptr
)和额外的元数据来处理指针和任何动态转换。
- 指针序列化记录在这里https://www.boost.org/doc/libs/1_79_0/libs/serialization/doc/tutorial.html#pointers
- 对象跟踪记录在这里:https://www.boost.org/doc/libs/1_79_0/libs/serialization/doc/special.html#objecttracking
作为旁注,在归档完成之前不要关闭文件流。遗憾的是,我知道执行它的唯一方法就是运行析构函数。只需删除多余的关闭符:
// saves using pointer
void save_ptr(const std::string &path, const animal *animal) {
std::ofstream f_out(path);
boost::archive::text_oarchive arch_out(f_out);
arch_out << animal;
}
// save using value
void save_val(const std::string &path, animal animal) {
std::ofstream f_out(path);
boost::archive::text_oarchive arch_out(f_out);
arch_out << animal;
}