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