C++ Boost

序列化

序列化包装器


二进制对象
数组
BOOST_STRONG_TYPEDEF
集合大小
名称-值对
组合
有时,为了支持某些底层数据的序列化,创建临时对象会很方便。这允许归档类为这种类型定义特殊处理。库包含几种用于不同目的的此类类型。

包装器需要由某些归档以特殊方式处理,因此这些包装器类的is_wrapper 特性被设置为 true。

二进制对象

二进制对象只是一系列存储为原始二进制数据的字节。这最有可能用于大量“轻量级”数据,例如像素图或嵌入式二进制文件。头文件 binary_object.hpp 包含构造函数

boost::serialization::binary_object(void * t, size_t size);
boost::serialization::make_binary_object(void * t, size_t size);
它将构造一个可以像任何其他对象一样序列化的临时二进制对象。其默认序列化是使用归档类原语save_binaryload_binary。请注意,它不会分配任何存储空间或创建任何对象。其唯一目的是将数据大小和地址作为一对传递给归档类。

数组

数组是同类数据类型的连续序列,例如内置的 C 数组、boost::array<T>std::vector<T>。此包装器的目的是支持归档类型(例如二进制归档),这些类型为相同类型对象的连续序列提供优化的序列化。头文件 array.hpp 包含函数

template <T>
boost::serialization::make_array(T* t, std::size_t size);
它将构造一个临时array 对象

template<class T>
class array
{
public:    
    typedef T value_type;
    array(value_type* t, std::size_t s);
    value_type* address() const;
    std::size_t count() const;
};
可以像任何其他对象一样序列化。其默认序列化是序列化每个数组元素。请注意,它不会分配任何存储空间或创建任何对象。其唯一目的是将数据类型、大小和地址传递给归档类。可以为同类数据的连续数组提供优化实现的归档类型应重载array 的序列化。

BOOST_STRONG_TYPEDEF

序列化包装器的另一个示例是BOOST_STRONG_TYPEDEF 模板。序列化库使用它们将特定类型的整数(例如 object_id、version 等)传递给归档类。鉴于这些整数现在可以根据其类型区分,XML 归档可以对这些类型应用特殊处理。例如,版本号以“version=12”的形式呈现为 XML 属性。在没有任何特定覆盖的情况下,这些类型会自动转换为底层整数类型,因此 XML 归档使用的特殊覆盖对于其他归档不是必需的。

集合大小

强类型定义的一个示例是头文件 collection_size_type.hpp 中的collection_size_type。此类型应用于序列化 C++ 集合的大小,以便归档可以为集合大小的序列化选择最佳整数表示。这是必要的,因为尽管std::size_t 保证是足够大的整数类型来表示特定平台上集合的大小,但归档可能希望以不同于此类型的方式序列化大小。例如,collection_size_type 可以在可移植的二进制归档中序列化为可变长度整数。

名称-值对

XML 归档提出了一个有点特殊的情况。XML 格式具有嵌套结构,该结构很好地映射到序列化系统使用的“递归类成员访问者”模式。但是,XML 与其他格式的不同之处在于它需要每个类数据成员的名称。我们的目标是在类序列化规范中添加此信息,同时仍然允许在任何归档中使用序列化代码。

我们的解决方案是将要序列化的类成员包装到名称-值对中。此结构在nvp.hpp中定义。它只是对数据成员的引用,以及指向const char * 的指针,该指针对应于 XML 名称。它实现了名称-值对的默认序列化函数。此默认操作只是忽略项目名称并以正常方式序列化数据值。对于不对名称-值对进行任何特殊规定的归档类,当序列化名称-值对时,将调用此操作。因此,当与不对此包装器进行任何特殊规定的归档一起使用时,将数据值包装到名称-值对中将不会有任何效果。

xml 归档类包含类似于以下内容的代码


// special treatment for name-value pairs.
template<class T>
xml_oarchive & operator&(const boost::serialization::nvp<T> & t)
{
    // write an xml start tag
    start_tag(t.name());

    // serialize the data as usual
    *this & t.value();

    // write an xml end tag
    end_tag(t.name());
}
要分配为 XML 数据项名称的最明显和最方便的名称是——令人惊讶的是——C++ 类数据成员的名称。因此,我们的序列化代码将如下所示

ar & make_nvp("my_variable", my_variable);
为了简化输入并增强可读性,定义了一个宏,以便我们可以编写

ar & BOOST_SERIALIZATION_NVP(my_variable);
类似地,存在一个宏定义,允许我们编写

BOOST_SERIALIZATION_BASE_OBJECT_NVP(my_base_class)
请注意,这些宏必须在类的命名空间中使用,并且在参数中不限定命名空间。

demo_gps.hpp包含所有数据成员的 NVP 包装器。demo_xml.cpp将数据保存并加载到 XML 归档中。此处是我们教程示例对应的 XML 归档示例。

组合

包装器应设计为可以根据需要组合。例如,要将二进制数据作为名称值对传递,请使用

ar & make_nvp("named_binary_object", make_binary_object(address, size));

© 版权所有 Robert Ramey 2002-2004。在 Boost 软件许可证版本 1.0 下分发。(请参阅随附文件 LICENSE_1_0.txt 或复制到 https://boost.ac.cn/LICENSE_1_0.txt)