C++ Boost Archive超详细讲解

 更新时间:2022年12月01日 10:27:04   作者:无水先生  
Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称

一、说明

对Boost.Serialization库的应用,存在如下内容:

Boost.Serialization 库可以将 C++ 程序中的对象转换为可以保存和加载以恢复对象的字节序列。有不同的数据格式可用于定义生成字节序列的规则。 Boost.Serialization 支持的所有格式仅适用于此库。例如,为 Boost.Serialization 开发的 XML 格式不应用于与不使用 Boost.Serialization 的程序交换数据。 XML 格式的唯一优点是它可以使调试更容易,因为 C++ 对象以可读格式保存。

二、关于Archive库

Boost.Serialization 的主要概念是存档。存档是表示序列化 C++ 对象的字节序列。可以将对象添加到存档中以对其进行序列化,然后再从存档中加载。为了恢复以前保存的 C++ 对象,假定相同的类型。

示例 64.1。使用 boost::archive::text_oarchive

#include <boost/archive/text_oarchive.hpp>
#include <iostream>
using namespace boost::archive;
int main()
{
  text_oarchive oa{std::cout};
  int i = 1;
  oa << i;
}

Boost.Serialization 提供归档类,例如 boost::archive::text_oarchive,它在 boost/archive/text_oarchive.hpp 中定义。此类可以将对象序列化为文本流。使用 Boost 1.56.0,示例 64.1 将 22 serialization::archive 11 1 写入标准输出流。

可以看出,boost::archive::text_oarchive 类型的对象 oa 可以像流一样使用 operator<< 序列化变量。但是,不应将存档视为存储任意数据的常规流。要恢复数据,您必须在存储数据时访问它,并以相同的顺序使用相同的数据类型。示例 64.2 序列化并恢复一个 int 类型的变量。

示例 64.2。使用 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 << '\n';
}
int main()
{
  save();
  load();
}

boost::archive::text_oarchive 类将数据序列化为文本流,而 boost::archive::text_iarchive 类从此类文本流中恢复数据。要使用这些类,请包含头文件 boost/archive/text_iarchive.hpp 和 boost/archive/text_oarchive.hpp。

档案的构造函数期望输入或输出流作为参数。流用于序列化或恢复数据。虽然示例 64.2 访问文件,但也可以使用其他流,例如字符串流。

示例 64.3。使用字符串流序列化

#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 << '\n';
}
int main()
{
  save();
  load();
}

Example 64.3

示例 64.3 使用字符串流将 1 写入标准输出以序列化数据。

到目前为止,只有原始类型被序列化。示例 64.4 显示了如何序列化用户定义类型的对象。

示例 64.4。使用成员函数序列化用户定义的类型

#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() << '\n';
}
int main()
{
  save();
  load();
}

为了序列化用户定义类型的对象,您必须定义成员函数 serialize()。当对象被序列化为字节流或从字节流恢复时调用此函数。因为 serialize() 用于序列化和恢复,所以除了 operator<< 和 operator>> 之外,Boost.Serialization 还支持运算符 operator&。使用 operator& 时,无需在 serialize() 中区分序列化和恢复。

序列化或恢复对象时,会自动调用 serialize()。它永远不应该被显式调用,因此应该被声明为私有的。如果声明为私有,则必须将类 boost::serialization::access 声明为友元,以允许 Boost.Serialization 访问成员函数。

可能存在不允许修改现有类以添加 serialize() 的情况。例如,标准库中的类就是如此。

示例 64.5。使用独立函数序列化

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <iostream>
#include <sstream>
using namespace boost::archive;
std::stringstream ss;
struct animal
{
  int legs_;
  animal() = default;
  animal(int legs) : legs_{legs} {}
  int legs() const { return legs_; }
};
template <typename Archive>
void serialize(Archive &ar, animal &a, const unsigned int version)
{
  ar & a.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() << '\n';
}
int main()
{
  save();
  load();
}

为了序列化不能修改的类型,可以定义独立函数 serialize(),如示例 64.5 所示。此函数需要对相应类型的对象的引用作为其第二个参数。

将 serialize() 作为独立函数实现需要可以从外部访问类的基本成员变量。在示例 64.5 中,serialize() 只能作为独立函数实现,因为 legs_ 不再是动物类的私有成员变量。

Boost.Serialization 为标准库中的许多类提供了 serialize() 函数。要序列化基于标准类的对象,需要包含额外的头文件。

示例 64.6。序列化字符串

#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() << '\n';
  std::cout << a.name() << '\n';
}
int main()
{
  save();
  load();
}

Example 64.6

示例 64.6 通过添加 name_ 扩展类 animal,这是一个 std::string 类型的成员变量。为了序列化此成员变量,必须包含头文件 boost/serialization/string.hpp 以提供适当的独立函数 serialize()。

如前所述,Boost.Serialization 为标准库中的许多类定义了 serialize() 函数。这些函数在头文件中定义,这些头文件的名称与标准中相应的头文件相同。因此,要序列化 ​​std::string 类型的对象,请包含头文件 boost/serialization/string.hpp,要序列化 ​​std::vector 类型的对象,请包含头文件 boost/serialization/vector.hpp。要包含哪个头文件是相当明显的。

到目前为止被忽略的 serialize() 的一个参数是版本。此参数有助于使存档向后兼容。示例 64.7 可以加载由示例 64.5 创建的存档。示例 64.5 中动物类的版本不包含名称。示例 64.7 在加载存档时检查版本号,并且仅在版本大于 0 时才访问名称。这允许它处理创建时没有名称的旧存档。

示例 64.7。与版本号的向后兼容性

#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_;
  if (version > 0)
    ar & a.name_;
}
BOOST_CLASS_VERSION(animal, 1)
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() << '\n';
  std::cout << a.name() << '\n';
}
int main()
{
  save();
  load();
}

宏 BOOST_CLASS_VERSION 为类分配版本号。示例 64.7 中类动物的版本号为 1。如果未使用 BOOST_CLASS_VERSION,版本号默认为 0。

版本号存储在存档中并且是其中的一部分。虽然在序列化期间使用通过 BOOST_CLASS_VERSION 宏为特定类指定的版本号,但在恢复时将 serialize() 的参数版本设置为存储在存档中的值。如果新版本的 animal 访问包含用旧版本序列化的对象的存档,则成员变量 name_ 不会被恢复,因为旧版本没有这样的成员变量。

  • 练习

创建一个程序,将 std::runtime_error 类型的对象序列化为一个文件并再次加载它。

到此这篇关于C++ Boost Archive超详细讲解的文章就介绍到这了,更多相关C++ Boost Archive内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 简单分析C语言中指针数组与数组指针的区别

    简单分析C语言中指针数组与数组指针的区别

    这篇文章主要介绍了C语言中指针数组与数组指针的区别,是C语言入门学习中的基础知识,需要的朋友可以参考下
    2015-11-11
  • Qt实现打地鼠游戏的方法详解

    Qt实现打地鼠游戏的方法详解

    这篇文章主要和大家详细介绍了如何利用Qt实现一个简单的打地鼠游戏,文中的示例代码讲解详细,具有一定的借鉴价值,需要的可以参考一下
    2022-10-10
  • C++ 通过pqxxlib库链接 PostgreSql数据库的详细过程

    C++ 通过pqxxlib库链接 PostgreSql数据库的详细过程

    这篇文章主要介绍了C++ 通过pqxxlib库链接 PostgreSql数据库,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-04-04
  • OpenCV实现高斯噪声

    OpenCV实现高斯噪声

    这篇文章主要为大家详细介绍了OpenCV实现高斯噪声,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-06-06
  • opencv3/C++ FLANN特征匹配方式

    opencv3/C++ FLANN特征匹配方式

    今天小编就为大家分享一篇opencv3/C++ FLANN特征匹配方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-12-12
  • OpenGL绘制三次Bezier曲线

    OpenGL绘制三次Bezier曲线

    这篇文章主要为大家详细介绍了OpenGL绘制三次Bezier曲线,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-04-04
  • 详解C语言中的getgrgid()函数和getgrnam()函数

    详解C语言中的getgrgid()函数和getgrnam()函数

    这篇文章主要介绍了详解C语言中的getgrgid()函数和getgrnam()函数,是C语言入门学习中的基础知识,需要的朋友可以参考下
    2015-08-08
  • 对C语言中sizeof细节的三点分析介绍

    对C语言中sizeof细节的三点分析介绍

    以下是对C语言中sizeof的细节进行了详细的分析介绍,需要的朋友可以参考下
    2013-07-07
  • 基于Qt OpenCV实现图像数据采集软件

    基于Qt OpenCV实现图像数据采集软件

    这篇文章主要为大家详细介绍了如何利用Qt+OpenCV实现图像数据采集软件,文中的示例代码讲解详细,对我学习或工作有一定参考价值,感兴趣的可以了解一下
    2022-07-07
  • C++中正则表达式的使用方法详解

    C++中正则表达式的使用方法详解

    几乎所有的编程语言都支持正则表达式。 C++从C++11开始直接支持正则表达式。除了编程语言之外,大多数文本处理程序都使用正则表达式。本文将探讨正则表达式的一般细节以及C++编程方面的细节,感兴趣的可以学习一下
    2022-05-05

最新评论