C++ Boost Archive超詳細(xì)講解
一、說明
對Boost.Serialization庫的應(yīng)用,存在如下內(nèi)容:
- Archive
- Pointers and References
- Serialization of Class Hierarchy Objects
- Wrapper Functions for Optimization
Boost.Serialization 庫可以將 C++ 程序中的對象轉(zhuǎn)換為可以保存和加載以恢復(fù)對象的字節(jié)序列。有不同的數(shù)據(jù)格式可用于定義生成字節(jié)序列的規(guī)則。 Boost.Serialization 支持的所有格式僅適用于此庫。例如,為 Boost.Serialization 開發(fā)的 XML 格式不應(yīng)用于與不使用 Boost.Serialization 的程序交換數(shù)據(jù)。 XML 格式的唯一優(yōu)點(diǎn)是它可以使調(diào)試更容易,因?yàn)?C++ 對象以可讀格式保存。
二、關(guān)于Archive庫
Boost.Serialization 的主要概念是存檔。存檔是表示序列化 C++ 對象的字節(jié)序列??梢詫ο筇砑拥酱鏅n中以對其進(jìn)行序列化,然后再從存檔中加載。為了恢復(fù)以前保存的 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 寫入標(biāo)準(zhǔn)輸出流。
可以看出,boost::archive::text_oarchive 類型的對象 oa 可以像流一樣使用 operator<< 序列化變量。但是,不應(yīng)將存檔視為存儲任意數(shù)據(jù)的常規(guī)流。要恢復(fù)數(shù)據(jù),您必須在存儲數(shù)據(jù)時訪問它,并以相同的順序使用相同的數(shù)據(jù)類型。示例 64.2 序列化并恢復(fù)一個 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 類將數(shù)據(jù)序列化為文本流,而 boost::archive::text_iarchive 類從此類文本流中恢復(fù)數(shù)據(jù)。要使用這些類,請包含頭文件 boost/archive/text_iarchive.hpp 和 boost/archive/text_oarchive.hpp。
檔案的構(gòu)造函數(shù)期望輸入或輸出流作為參數(shù)。流用于序列化或恢復(fù)數(shù)據(jù)。雖然示例 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();
}示例 64.3 使用字符串流將 1 寫入標(biāo)準(zhǔn)輸出以序列化數(shù)據(jù)。
到目前為止,只有原始類型被序列化。示例 64.4 顯示了如何序列化用戶定義類型的對象。
示例 64.4。使用成員函數(shù)序列化用戶定義的類型
#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();
}為了序列化用戶定義類型的對象,您必須定義成員函數(shù) serialize()。當(dāng)對象被序列化為字節(jié)流或從字節(jié)流恢復(fù)時調(diào)用此函數(shù)。因?yàn)?serialize() 用于序列化和恢復(fù),所以除了 operator<< 和 operator>> 之外,Boost.Serialization 還支持運(yùn)算符 operator&。使用 operator& 時,無需在 serialize() 中區(qū)分序列化和恢復(fù)。
序列化或恢復(fù)對象時,會自動調(diào)用 serialize()。它永遠(yuǎn)不應(yīng)該被顯式調(diào)用,因此應(yīng)該被聲明為私有的。如果聲明為私有,則必須將類 boost::serialization::access 聲明為友元,以允許 Boost.Serialization 訪問成員函數(shù)。
可能存在不允許修改現(xiàn)有類以添加 serialize() 的情況。例如,標(biāo)準(zhǔn)庫中的類就是如此。
示例 64.5。使用獨(dú)立函數(shù)序列化
#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();
}為了序列化不能修改的類型,可以定義獨(dú)立函數(shù) serialize(),如示例 64.5 所示。此函數(shù)需要對相應(yīng)類型的對象的引用作為其第二個參數(shù)。
將 serialize() 作為獨(dú)立函數(shù)實(shí)現(xiàn)需要可以從外部訪問類的基本成員變量。在示例 64.5 中,serialize() 只能作為獨(dú)立函數(shù)實(shí)現(xiàn),因?yàn)?legs_ 不再是動物類的私有成員變量。
Boost.Serialization 為標(biāo)準(zhǔn)庫中的許多類提供了 serialize() 函數(shù)。要序列化基于標(biāo)準(zhǔn)類的對象,需要包含額外的頭文件。
示例 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();
}示例 64.6 通過添加 name_ 擴(kuò)展類 animal,這是一個 std::string 類型的成員變量。為了序列化此成員變量,必須包含頭文件 boost/serialization/string.hpp 以提供適當(dāng)?shù)莫?dú)立函數(shù) serialize()。
如前所述,Boost.Serialization 為標(biāo)準(zhǔn)庫中的許多類定義了 serialize() 函數(shù)。這些函數(shù)在頭文件中定義,這些頭文件的名稱與標(biāo)準(zhǔn)中相應(yīng)的頭文件相同。因此,要序列化 ??std::string 類型的對象,請包含頭文件 boost/serialization/string.hpp,要序列化 ??std::vector 類型的對象,請包含頭文件 boost/serialization/vector.hpp。要包含哪個頭文件是相當(dāng)明顯的。
到目前為止被忽略的 serialize() 的一個參數(shù)是版本。此參數(shù)有助于使存檔向后兼容。示例 64.7 可以加載由示例 64.5 創(chuàng)建的存檔。示例 64.5 中動物類的版本不包含名稱。示例 64.7 在加載存檔時檢查版本號,并且僅在版本大于 0 時才訪問名稱。這允許它處理創(chuàng)建時沒有名稱的舊存檔。
示例 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,版本號默認(rèn)為 0。
版本號存儲在存檔中并且是其中的一部分。雖然在序列化期間使用通過 BOOST_CLASS_VERSION 宏為特定類指定的版本號,但在恢復(fù)時將 serialize() 的參數(shù)版本設(shè)置為存儲在存檔中的值。如果新版本的 animal 訪問包含用舊版本序列化的對象的存檔,則成員變量 name_ 不會被恢復(fù),因?yàn)榕f版本沒有這樣的成員變量。
- 練習(xí)
創(chuàng)建一個程序,將 std::runtime_error 類型的對象序列化為一個文件并再次加載它。
到此這篇關(guān)于C++ Boost Archive超詳細(xì)講解的文章就介紹到這了,更多相關(guān)C++ Boost Archive內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
簡單分析C語言中指針數(shù)組與數(shù)組指針的區(qū)別
這篇文章主要介紹了C語言中指針數(shù)組與數(shù)組指針的區(qū)別,是C語言入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下2015-11-11
C++?通過pqxxlib庫鏈接?PostgreSql數(shù)據(jù)庫的詳細(xì)過程
這篇文章主要介紹了C++?通過pqxxlib庫鏈接?PostgreSql數(shù)據(jù)庫,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-04-04
詳解C語言中的getgrgid()函數(shù)和getgrnam()函數(shù)
這篇文章主要介紹了詳解C語言中的getgrgid()函數(shù)和getgrnam()函數(shù),是C語言入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下2015-08-08
對C語言中sizeof細(xì)節(jié)的三點(diǎn)分析介紹
以下是對C語言中sizeof的細(xì)節(jié)進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以參考下2013-07-07
基于Qt OpenCV實(shí)現(xiàn)圖像數(shù)據(jù)采集軟件
這篇文章主要為大家詳細(xì)介紹了如何利用Qt+OpenCV實(shí)現(xiàn)圖像數(shù)據(jù)采集軟件,文中的示例代碼講解詳細(xì),對我學(xué)習(xí)或工作有一定參考價值,感興趣的可以了解一下2022-07-07

