Boost::serialization 如何在存档中存储用户定义的 类?

How does Boost::serialization store user-defined classes in archives?

我有一个用户定义的对象(称之为 Foo),它由一些原始变量以及其他(外部库)对象组成,这些对象已经包含 serialize 函数的实现。 我想知道存档文件的结构,以及该结构是否通用(例如,在文本存档和二进制存档之间)。 当我在文本编辑器中打开文本存档时,第一个字符是 22 serialization::archive 19 0 0。 接下来似乎是我的用户定义对象的所有数据。

我的问题是:那些首字母分别对应什么?如果我尝试将我的文件的内容输出到不是 Foo 的内容中,如下所示:

bool bool1;
bool bool2;

ia >> bool1 >> bool2;

它似乎只输出前几个零 -- 它对任何存档都这样做吗? 如果是这样,通过读入适当的类型从该存档中读出 Foo 的所有成员变量是否合理,如:

bool bool1;
bool bool2;
double Foo_member1;
std::string Foo_member2;

ia >> bool1 >> bool2 >> Foo_member1 >> Foo_member2;

最后,这种结构是否也来自任何其他类型的存档(例如二进制存档)?

it seems to just output the first few zeros

你是什么意思?您用 不确定值 序列化了两个变量(您从未初始化它们)。你不应该期待零。您也不应该期待任何特定的布局(它由存档类型、版本、库版本和平台架构决定)。

like to know how the archive files are structured, and whether that structure is general

这取决于存档。它“一般”(对于一般的某些定义)。然而,大多数存档格式包含描述其结构的最小元数据(它们不能以非顺序方式“访问”或“遍历”,也没有某种“可反射”模式)。如果您需要这些类型的序列化功能,请查看其他功能(protobuf、msgpack、bson、XML/XSD 等)。

最能满足您好奇心的一种存档类型是 XML 存档类型。您会发现您需要为 XML 元素提供语义信息,例如

Live On Coliru

#include <boost/archive/xml_oarchive.hpp>
#include <iostream>

int main() {
    using boost::serialization::make_nvp;
    {
        boost::archive::xml_oarchive oa(std::cout);

        int a = 42, b = 99, c = a * b;
        oa << make_nvp("a", a) << make_nvp("b", b) << make_nvp("c", c);
    } // closes the archive
}

结果是

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="19">
  <a>42</a>
  <b>99</b>
  <c>4158</c>
</boost_serialization>

这至少会为版本 (19) 和类似信息提供一些可识别的上下文。例如。与对象跟踪和身份、RTTI 映射和导出的 class 密钥等相关

And if so, is it reasonable to read out all of the member variables of Foo from that archive by just reading into the appropriate types

是的,但也许不是。您必须履行的合同是以完全相同的顺序(反)序列化完全相同类型的数据。任何你管理的方式都很好。典型的方法是为你的类型实现serialize,而不是单独序列化成员(Law Of Demeter and simple Encapsulation):

Live On Coliru

#include <boost/archive/xml_oarchive.hpp>

namespace MyLib {
    struct Foo {
        bool        bool1;
        bool        bool2;
        double      Foo_member1;
        std::string Foo_member2;
    };

    template <typename Ar>
    void serialize(Ar& ar, Foo& foo, unsigned /*version*/)
    {
        ar& BOOST_NVP(foo.bool1) & BOOST_NVP(foo.bool2) &
            BOOST_NVP(foo.Foo_member1) & BOOST_NVP(foo.Foo_member2);
    }
} // namespace MyLib

#include <cmath> // for M_PI...
#include <iostream>
int main() {
    using boost::serialization::make_nvp;
    {
        boost::archive::xml_oarchive oa(std::cout);

        MyLib::Foo foo{true, false, M_PI, "Hello world"};
        oa << make_nvp("foo", foo);
    } // closes the archive
}

版画

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="19">
<foo class_id="0" tracking_level="0" version="0">
    <foo.bool1>1</foo.bool1>
    <foo.bool2>0</foo.bool2>
    <foo.Foo_member1>3.14159265358979312e+00</foo.Foo_member1>
    <foo.Foo_member2>Hello world</foo.Foo_member2>
</foo>
</boost_serialization>

警告

这听起来确实有点像您将存档误认为是具有某种标准格式的随机访问数据流。查看更多Archives are not streams