天天看點

Boost Serialization 庫(一個有效的調試工具)

使用了 Boost Serialization 的 Hello World

在執行更重要的任務之前,我們先來驗證一下概念。在以下的 清單 1 中,您會看到一個字元串,它的值被轉儲到一個歸檔檔案中。在以下的 清單 2 中,将此歸檔檔案的内容恢複,以驗證此字元串的值是否與原來相符。

清單 1. 将字元串内容儲存到文本歸檔檔案中

#include <boost/archive/text_oarchive.hpp> 
#include <iostream> 
#include <fstream> 

void save() 
{ 
  std::ofstream file("archive.txt"); 
  boost::archive::text_oarchive oa(file); 
  std::string s = "Hello World!\n"; 
  oa << s; 
} 

int main()
{
    save();
}
      

現在将内容加載回來。

清單 2. 将字元串的内容加載到文本歸檔檔案中

#include <boost/archive/text_iarchive.hpp> 
#include <iostream> 
#include <fstream> 

void load() 
{ 
  std::ifstream file("archive.txt"); 
  boost::archive::text_iarchive ia(file); 
  std::string s;
  ia >> s; 
  std::cout << s << std::endl; 
}

int main()
{
    load();
}
      

不出所料,清單 2 的輸出内容是 “Hello World”。

現在,我們仔細看一下代碼。Boost 建立了一個文本歸檔檔案(一個文本檔案),它含有需要轉儲的内容。為了轉儲這些内容,您需要建立了一個

text_oarchive

。為了恢複内容,您還建立了一個

text_iarchive

,并分别在頭檔案 text_oarchive.hpp 和 text_iarchive.hpp 中聲明它。轉儲和恢複内容很直覺,使用

<<

>>

運算符,其工作原理非常類似于流 I/O,除了要将内容轉儲到檔案中,然後過一段時間以後再從該檔案中恢複。

不過,您可能想隻用一個

&

運算符完成轉儲和恢複操作,而不是使用上述的兩個不同運算符。下面的 清單 3 顯示了相關的使用方法。

清單 3. 使用 & 運算符執行 “轉儲 - 恢複” 操作

#include <boost/archive/text_iarchive.hpp> 
#include <boost/archive/text_oarchive.hpp> 
#include <iostream> 
#include <fstream> 

void save() 
{ 
  std::ofstream file("archive.txt"); 
  boost::archive::text_oarchive oa(file); 
  std::string s = "Hello World!\n"; 
  oa & s; // has same effect as oa << s;
} 

void load() 
{ 
  std::ifstream file("archive.txt"); 
  boost::archive::text_iarchive ia(file); 
  std::string s;
  ia & s; 
  std::cout << s << std::endl; 
}
      

我們來看一下轉儲的文本檔案:

22 serialization::archive 9 13 Hello World!
      

請注意,在以後的 Boost 版本中,文本檔案的内容和格式可能有所不同,是以應用程式代碼最好不要依賴于内部歸檔檔案内容。

建立一個 XML 歸檔檔案

如果您想使用 XML 歸檔檔案,而不是文本歸檔檔案,則必須包含來自 Boost 源的頭檔案 xml_iarchive.hpp 和 xml_oarchive.hpp。這些頭檔案聲明或定義了 XML 歸檔檔案語義。但是,該 “轉儲 - 恢複” 操作與應用于文本歸檔檔案的 “轉儲 - 恢複” 操作仍有些微不同之處:需要将資料打包到一個名為

BOOST_SERIALIZATION_NVP

的宏中。下面的 清單 4 提供了相關的代碼。

清單 4. 從 XML 歸檔檔案執行 “轉儲 - 恢複” 操作

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

void save() 
{ 
  std::ofstream file("archive.xml"); 
  boost::archive::xml_oarchive oa(file); 
  std::string s = "Hello World!\n"; 
  oa & BOOST_SERIALIZATION_NVP(s); 
} 

void load() 
{ 
  std::ifstream file("archive.xml"); 
  boost::archive::xml_iarchive ia(file); 
  std::string s;
  ia & BOOST_SERIALIZATION_NVP(s); 
  std::cout << s << std::endl; 
}
      

清單 5 顯示了 XML 歸檔檔案的内容。變量名可充當标記 (

<s>Hello World!</s>

)。

清單 5. XML 歸檔檔案的内容

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="9">
<s>Hello World!</s>
</boost_serialization>
      

回頁首

還有其他哪些内容可以序列化?

以下内容才是精華。無需額外編碼,就可以将

C++

程式設計語言中的很多元素序列化。類、類指針、數組和 Standard Template Library (STL) 集合都可以被序列化。下面的 清單 6 提供了一個包含數組的樣例。

清單 6. 對整數數組執行 “轉儲 - 恢複” 操作

#include <boost/archive/xml_oarchive.hpp> 
#include <boost/archive/xml_iarchive.hpp> 
#include <iostream> 
#include <fstream> 
#include <algorithm>
#include <iterator>

void save() 
{ 
  std::ofstream file("archive.xml"); 
  boost::archive::xml_oarchive oa(file); 
  int array1[] = {34, 78, 22, 1, 910};
  oa & BOOST_SERIALIZATION_NVP(array1); 
} 

void load() 
{ 
  std::ifstream file("archive.xml"); 
  boost::archive::xml_iarchive ia(file); 
  int restored[5]; // Need to specify expected array size
  ia >> BOOST_SERIALIZATION_NVP(restored);
  std::ostream_iterator<int> oi(std::cout, " ");
  std::copy(a, a+5, oi);
} 

int main() 
{ 
  save(); 
  load(); 
}
      

這很簡單。轉儲過程與字元串類一樣;但在恢複過程中,需要指定預期的數組大小。否則,程式會崩潰。清單 7 提供了 清單 6 中代碼的已轉儲的 XML 歸檔檔案。

清單 7. 通過數組轉儲建立的 XML 歸檔檔案

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="9">
<array1>
	<count>5</count>
	<item>34</item>
	<item>78</item>
	<item>22</item>
	<item>1</item>
	<item>910</item>
</array1>
</boost_serialization>
      

是否可以僅通過指定指針

int* restored

完成此操作并為您恢複數組?答案是否定的。必須每次都指定大小。如果認真回答此問題的話,答案是對基本類型的指針進行序列化非常複雜。

回頁首

序列化 STL 集合

要序列化 STL 清單和向量,則必須了解每個 STL 類型,應用程式代碼必須包含來自 Serialization 源的具有類似名稱的頭檔案。對于清單,需要包含 boost/serialization/list.hpp 等等。請注意,對于清單和向量,在将資訊加載回來的過程中,不需要提供任何大小和範圍資訊,這也是相對于具有相同功能的應用程式容器,人們更喜歡使用 STL 容器的另一個原因。清單 8 顯示了用于序列化 STL 集合的代碼。

清單 8. 序列化 STL 集合

#include <boost/archive/xml_oarchive.hpp> 
#include <boost/archive/xml_iarchive.hpp> 
#include <boost/serialization/list.hpp>
#include <boost/serialization/vector.hpp>
#include <iostream> 
#include <fstream> 
#include <algorithm>
#include <iterator>

void save() 
{ 
  std::ofstream file("archive.xml"); 
  boost::archive::xml_oarchive oa(file); 
  float array[] = {34.2, 78.1, 22.221, 1.0, -910.88};
  std::list<float> L1(array, array+5);
  std::vector<float> V1(array, array+5);
  oa & BOOST_SERIALIZATION_NVP(L1); 
  oa & BOOST_SERIALIZATION_NVP(V1); 
}

void load() 
{ 
  std::ifstream file("archive.xml"); 
  boost::archive::xml_iarchive ia(file); 
  std::list<float> L2;
  ia >> BOOST_SERIALIZATION_NVP(L2); // No size/range needed

  std::vector<float> V2;
  ia >> BOOST_SERIALIZATION_NVP(V2); // No size/range needed

  std::ostream_iterator<float> oi(std::cout, " ");
  std::copy(L2.begin(), L2.end(), oi);
  std::copy(V2.begin(), V2.end(), oi);
}
      

清單 9 顯示了一個 XML 歸檔檔案。

清單 9. 使用 STL 容器的轉儲歸檔檔案

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="9">
<L1>
	<count>5</count>
	<item_version>0</item_version>
	<item>34.200001</item>
	<item>78.099998</item>
	<item>22.221001</item>
	<item>1</item>
	<item>-910.88</item>
</L1>
<V1>
	<count>5</count>
	<item_version>0</item_version>
	<item>34.200001</item>
	<item>78.099998</item>
	<item>22.221001</item>
	<item>1</item>
	<item>-910.88</item>
</V1>
</boost_serialization>
      

回頁首

序列化自己的類型

是否想序列化自己的類型?毫無疑問您是願意的!我們将采用一個表示日期的結構作為一個簡單的示例:

typedef struct date { 
   unsigned int m_day;
   unsigned int m_month;
   unsigned int m_year;
} date; 
      

要對某個類進行序列化,則必須在類定義中定義一個名為

serialize

的方法。在轉儲和恢複類的過程中會調用該方法。以下是對

serialize

方法的聲明:

template<class Archive>
    void serialize(Archive& archive, const unsigned int version)
    {
        //… your custom code here
    }
      

在第二段代碼片段中,

serialize

是一個模闆函數,第一個參數應該是對 Boost 歸檔檔案的引用。那麼,XML 歸檔檔案的代碼會是什麼樣呢?請看以下代碼:

template<class Archive>
    void serialize(Archive& archive, const unsigned int version)
    {
        archive & BOOST_SERIALIZATION_NVP(m_day);
        archive & BOOST_SERIALIZATION_NVP(m_month);
        archive & BOOST_SERIALIZATION_NVP(m_year);
    }
      

下面的 清單 10 提供了完整代碼。

清單 10. 日期類型的 “轉儲 - 恢複”

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

typedef struct date { 
    unsigned int m_day;
    unsigned int m_month;
    unsigned int m_year;

    date( int d,  int m,  int y) : m_day(d), m_month(m), m_year(y) 
    {}
    date() : m_day(1), m_month(1), m_year(2000) 
    {}
    friend std::ostream& operator << (std::ostream& out, date& d) 
    {
        out << "day:" << d.m_day 
              << " month:" << d.m_month
	<< " year:" << d.m_year;
        return out;
    }
    template<class Archive>
    void serialize(Archive& archive, const unsigned int version)
    {
        archive & BOOST_SERIALIZATION_NVP(m_day);
        archive & BOOST_SERIALIZATION_NVP(m_month);
        archive & BOOST_SERIALIZATION_NVP(m_year);
    }
} date;

void save() 
{ 
  std::ofstream file("archive.xml"); 
  boost::archive::xml_oarchive oa(file); 
  date d(15, 8, 1947);
  oa & BOOST_SERIALIZATION_NVP(d); 
} 

void load() 
{ 
  std::ifstream file("archive.xml"); 
  boost::archive::xml_iarchive ia(file); 
  date dr;
  ia >> BOOST_SERIALIZATION_NVP(dr); 
  std::cout << dr;
}
      

請注意,除了定義

serialize

方法之外,并沒有為了處理使用者定義類型而執行任何特殊操作。以上代碼運作正常,但有一個很明顯的問題:可能需要序列化來自第三方的類型,而它們的類聲明可能是無法修改的。對于這種情況,您可以使用

serialize

的非侵入性(non-intrusive)版本,以便可以在類範圍之外定義該方法。下面的 清單11 顯示了

date

類的非侵入性

serialize

方法。請注意,如果

serialize

方法已在全局範圍内定義,該代碼仍然有效;但是,好的程式設計實踐是在相關命名空間内定義該方法。

清單 11. serialize 方法的非侵入性版本

namespace boost {
namespace serialization {

template<class Archive>
void serialize(Archive& archive, date& d, const unsigned int version)
{
    archive & BOOST_SERIALIZATION_NVP(d.m_day);
    archive & BOOST_SERIALIZATION_NVP(d.m_month);
    archive & BOOST_SERIALIZATION_NVP(d.m_year);
}

} // namespace serialization
} // namespace boost
      

清單 12 顯示了 date 類型的 XML 歸檔檔案。

清單 12. 使用者定義類型的 XML 歸檔檔案

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="9">
<d class_id="0" tracking_level="0" version="0">
	<d.m_day>15</d.m_day>
	<d.m_month>8</d.m_month>
	<d.m_year>1947</d.m_year>
</d>
</boost_serialization>
      

回頁首

處理類層次結構

類通常是從其他類派生的,是以您需要找到一種能夠在序列化派生類的同時序列化基類的方法。對于基類和派生類,都必須定義

serialize

方法。另外,還需要調整派生類的

serialize

定義,如 清單 13 所示。

清單 13. 序列化基類

template<class Archive>
void serialize(Archive& archive, const unsigned int version)
{
     // serialize base class information
     archive & boost::serialization::base_object<Base Class>(*this);
     // serialize derived class members
     archive & derived-class-member1;
     archive & derived-class-member2;
     // … 
}
      

直接在派生類的

serialize

方法中調用基類的

serialize

方法是一個很糟糕的想法。盡管能夠這麼做,但是無法追蹤類版本控制(稍後講述),或者無法消除生成的歸檔檔案中的備援。避免這種錯誤的一種推薦編碼方式是在所有類中将

serialize

方法設定為 private,并在所有将要序列化的類中使用

friend class boost::serialization::access

聲明。

通過基類指針轉儲派生類

通過指針轉儲派生類是完全有可能的;但是,該類和派生類都應該有各自的已定義的

serialize

方法。還有,您需要在轉儲和恢複過程中調用以下方法。

<archive name>.register_type<derived-type name>( )      

假設

date

類是從一個名為

base

的類派生出來的。清單 14 顯示了應該在

save

load

方法中加入哪些代碼。

清單 14. 使用基類指針實作序列化

void save() 
{ 
  std::ofstream file("archive.xml"); 
  boost::archive::xml_oarchive oa(file); 
  oa.register_type<date>( );
  base* b = new date(15, 8, 1947);
  oa & BOOST_SERIALIZATION_NVP(b); 
} 

void load() 
{ 
  std::ifstream file("archive.xml"); 
  boost::archive::xml_iarchive ia(file); 
  ia.register_type<date>( );
  base *dr;
  ia >> BOOST_SERIALIZATION_NVP(dr); 
  date* dr2 = dynamic_cast<date*> (dr); 
  std::cout << dr2;
}
      

在這裡,在轉儲和恢複過程中使用了

base

指針。但序列化的實際上是

date

對象。在轉儲和恢複之前,已經在這兩個類中注冊了 date 類型。

在執行 “轉儲 - 恢複” 操作過程中使用對象指針

可以使用對象指針進行轉儲和恢複。這樣做很有意思。您期望什麼樣的 XML 歸檔檔案的内容?當然,轉儲指針值不會有問題。您需要轉儲實際對象,然後将其還原。此外,指向同一個對象的多個指針又該如何呢?如果 XML 歸檔檔案具有同一個已轉儲對象的多個副本,那麼顯然不太好。Boost Serialization 的一大優勢是無論在何處(包括用于指針),所用的文法幾乎都是一樣的。以下的 清單15 是 清單 10 的修改版。

清單 15. 使用指針執行 “轉儲 - 恢複” 操作

void save() 
{ 
  std::ofstream file("archive.xml"); 
  boost::archive::xml_oarchive oa(file); 
  date* d = new date(15, 8, 1947);
  std::cout << d << std::endl;
  oa & BOOST_SERIALIZATION_NVP(d); 
  // … other code follows
} 

void load() 
{ 
  std::ifstream file("archive.xml"); 
  boost::archive::xml_iarchive ia(file); 
  date* dr;
  ia >> BOOST_SERIALIZATION_NVP(dr); 
  std::cout << dr << std::endl;
  std::cout << *dr;
}
      

請注意,在此清單中,

d

dr

的值是不同的,但内容相同。清單 16 顯示了 清單 15 代碼的 XML 歸檔檔案。

清單 16. 使用指針的 XML 歸檔檔案

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="9">
<d class_id="0" tracking_level="1" version="0" object_id="_0">
	<d.m_day>15</d.m_day>
	<d.m_month>8</d.m_month>
	<d.m_year>1947</d.m_year>
</d>
</boost_serialization>
      

現在,請考慮以下情況:将兩個指針轉儲到同一個對象并觀察用于相同對象的歸檔檔案是什麼樣子的。清單 17 對 清單 15 中的代碼稍微進行了一些修改。

清單 17. 使用指針執行 “轉儲 - 恢複” 操作

void save() 
{ 
  std::ofstream file("archive.xml"); 
  boost::archive::xml_oarchive oa(file); 
  date* d = new date(15, 8, 1947);
  std::cout << d << std::endl;
  oa & BOOST_SERIALIZATION_NVP(d); 
  date* d2 = d;
  oa & BOOST_SERIALIZATION_NVP(d2); 
  // … other code follows
} 

void load() 
{ 
  std::ifstream file("archive.xml"); 
  boost::archive::xml_iarchive ia(file); 
  date* dr;
  ia >> BOOST_SERIALIZATION_NVP(dr); 
  std::cout << dr << std::endl;
  std::cout << *dr;
  date* dr2;
  ia >> BOOST_SERIALIZATION_NVP(dr2); 
  std::cout << dr2 << std::endl;
  std::cout << *dr2;
}
      

下面的 清單 18 提供了 清單 17 中代碼的 XML 歸檔檔案。觀察如何處理第二個指針;此外,隻有一個對象被轉儲。

清單 18. 包含作為指針的 d2 的 XML 歸檔檔案

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="9">
<d class_id="0" tracking_level="1" version="0" object_id="_0">
	<d.m_day>15</d.m_day>
	<d.m_month>8</d.m_month>
	<d.m_year>1947</d.m_year>
</d>
<d2 class_id_reference="0" object_id_reference="_0"></d2>
</boost_serialization>
      

對于引用的處理方法與使用者應用程式代碼中一樣。盡管如此,請注意,在恢複過程中,建立了兩個獨特的對象。是以,歸檔檔案應該儲存兩個具有相同值的對象。與使用指針時的情況不同,以下是歸檔檔案的内容,其中的

d2

是清單 17 中的一個引用(參見下面的 清單 19)。

清單 19.包含作為 d 的引用 d2 的 XML 歸檔檔案

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="9">
<d class_id="0" tracking_level="0" version="0">
	<d.m_day>15</d.m_day>
	<d.m_month>8</d.m_month>
	<d.m_year>1947</d.m_year>
</d>
<d2>
	<d.m_day>15</d.m_day>
	<d.m_month>8</d.m_month>
	<d.m_year>1947</d.m_year>
</d2>
</boost_serialization>
      

回頁首

将 serialize 拆分成 save 和 load

有時候,您不想使用同樣的

serialize

方法來轉儲和恢複對象。在這種情況下,您可以将

serialize

方法拆分成兩個方法,即

save

load

,它們具有類似的簽名。這兩個方法都是之前定義的

serialize

方法的一部分。此外,需要添加

BOOST_SERIALIZATION_SPLIT_MEMBER

宏作為類定義的一部分。清單 20 顯示了這些方法是什麼樣子。

清單 20. 将 serialize 方法拆分成 save 和 load 方法

template<class Archive>
void save(Archive& archive, const unsigned int version) const
{
//… 
} 

template<class Archive>
void load(Archive& archive, const unsigned int version)
{
//…
} 

BOOST_SERIALIZATION_SPLIT_MEMBER( ) // must be part of class
      

注意

save

方法簽名後的

const

。如果沒有

const

限定符,該代碼将無法編譯。對于

date

類,清單 21 顯示了這些方法現在是什麼樣子。

清單 21. date 類的 save 和 load 方法

template<class Archive>
void save(Archive& archive, const unsigned int version) const
{
    archive << BOOST_SERIALIZATION_NVP(m_day);
    archive << BOOST_SERIALIZATION_NVP(m_month);
    archive << BOOST_SERIALIZATION_NVP(m_year)
} 

template<class Archive>
void load(Archive& archive, const unsigned int version)
{
    archive >> BOOST_SERIALIZATION_NVP(m_day);
    archive >> BOOST_SERIALIZATION_NVP(m_month);
    archive >> BOOST_SERIALIZATION_NVP(m_year)
} 

BOOST_SERIALIZATION_SPLIT_MEMBER( ) // must be part of class
      

回頁首

了解版本控制

serialize

save

load

的方法簽名都使用無符号整數版本作為最後一個參數。這些數字有什麼用?随着時間變化,類的内部變量名稱可能發生變化,添加新的字段或移除已有字段,等等。這是軟體開發過程中的自然程序,除了歸檔檔案仍然儲存着關于資料類型原有狀态的資訊。為了規避這個問題,需要使用版本号。

我們舉一個

date

類的例子。假設您在

date

類中引入一個名為

m_tag

、類型為

string

的字段。該類以前的版本以版本 0 的形式在歸檔檔案中轉儲,如 清單 12 所示。下面的 清單 22 顯示了該類的

load

方法(您可能已經使用了

serialize

,但這裡使用

load

提供了更清晰的實作)。

清單 22. 使用版本控制處理更新的類字段

template<class Archive>
void load(Archive& archive, const unsigned int version)
{
    archive >> BOOST_SERIALIZATION_NVP(m_day);
    archive >> BOOST_SERIALIZATION_NVP(m_month);
    archive >> BOOST_SERIALIZATION_NVP(m_year);
    if (version > 0) 
         archive >> BOOST_SERIALIZATION_NVP(m_tag);
} 
      

很明顯,合理使用版本控制可以讓該代碼與早先版本軟體中的舊歸檔檔案一起使用。

回頁首

使用共享指針

共享指針是一項經常使用且功能極其強大的程式設計技術。再次強調,Boost Serialization 一個主要優勢在于能輕松将共享指針序列化,并保持目前所知的文法不變。唯一要注意的是,必須在應用程式代碼中包含 boost/serialization/shared_ptr.hpp 頭檔案。從修改 清單 15 并使用

boost::shared_ptr

指針代替普通指針開始。代碼如下面的 清單 23 所示。

清單 23. 使用共享指針執行 “轉儲 - 恢複” 操作

void save() 
{ 
  std::ofstream file("archive.xml"); 
  boost::archive::xml_oarchive oa(file); 
  boost::shared_ptr<date> d (new date(15, 8, 1947));
  oa & BOOST_SERIALIZATION_NVP(d); 
  // … other code follows
} 

void load() 
{ 
  std::ifstream file("archive.xml"); 
  boost::archive::xml_iarchive ia(file); 
  boost::shared_ptr<date> dr;
  ia >> BOOST_SERIALIZATION_NVP(dr); 
  std::cout << *dr;
}
      

序列化搞定了一切?還沒有。關于 Serialization 支援什麼,不支援什麼,還有一些使用限制。例如,如果指向棧對象的指針的轉儲早于實際對象,那麼 Boost Serialization 就會崩潰。需要先轉儲對象,然後才能轉儲指向對象的指針(請注意,指針可以單獨轉儲,不需要先轉儲對象)。參見 清單 24 中的示例:

清單 24. 指向棧對象的指針需要在實際對象之後轉儲

void save() 
{ 
  std::ofstream file("archive.xml"); 
  boost::archive::xml_oarchive oa(file); 
  date d(15, 8, 1947);
  std::cout << d << std::endl;
  date* d2 = &d;
  oa & BOOST_SERIALIZATION_NVP(d); 
  oa & BOOST_SERIALIZATION_NVP(d2); 
} 

void load() 
{ 
  std::ifstream file("archive.xml"); 
  boost::archive::xml_iarchive ia(file); 
  date dr;
  ia >> BOOST_SERIALIZATION_NVP(dr); 
  std::cout << dr << std::endl;
  date* dr2;
  ia >> BOOST_SERIALIZATION_NVP(dr2); 
  std::cout << dr2 << std::endl;
}
      

在此清單中,無法在

d

之前轉儲

d2

。如果檢視 XML 歸檔檔案,就會很清楚這一點:

d2

作為

d

的一個引用進行轉儲的(參見 清單 25)。

清單 25. 在 XML 歸檔檔案中,對象及其指針均被轉儲

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="9">
<d class_id="0" tracking_level="1" version="0" object_id="_0">
	<d.m_day>15</d.m_day>
	<d.m_month>8</d.m_month>
	<d.m_year>1947</d.m_year>
</d>
<d2 class_id_reference="0" object_id_reference="_0"></d2>
</boost_serialization>
      

如果有多個指針指向同一個對象,Serialization 會使用

class_id_reference

将指針與原對象關聯起來(每個對象都有一個唯一的類 ID)。原對象的每個後續指針都會将

object_id_reference

改成

_1

_2

,以此類推。

回頁首

結束語

本文到這就結束了。您已經了解了 Boost Serialization 究竟是什麼;如何建立和使用文本與 XML 歸檔檔案;以及還有如何轉儲和恢複普通的舊的資料類型(STL 集合、類、類指針、共享指針和數組)。本文還簡單介紹了如何使用序列化和版本控制來處理類的層次結構。序列化是一個功能強大的工具。在代碼中,可以通過對序列化進行善加利用使調試變得更輕松。

參考資料

學習

  • 擷取 安裝 Boost 所需的知識。
  • AIX and UNIX 專區:developerWorks 的“AIX and UNIX 專區”提供了大量與 AIX 系統管理的所有方面相關的資訊,您可以利用它們來擴充自己的 UNIX 技能。
  • AIX and UNIX 新手入門:通路“AIX and UNIX 新手入門”頁面可了解更多關于 AIX 和 UNIX 的内容。
  • AIX and UNIX 專題彙總:AIX and UNIX 專區已經為您推出了很多的技術專題,為您總結了很多熱門的知識點。我們在後面還會繼續推出很多相關的熱門專題給您,為了友善您的通路,我們在這裡為您把本專區的所有專題進行彙總,讓您更友善的找到您需要的内容。
  • AIX and UNIX 下載下傳中心:在這裡你可以下載下傳到可以運作在 AIX 或者是 UNIX 系統上的 IBM 伺服器軟體以及工具,讓您可以提前免費試用他們的強大功能。
  • IBM Systems Magazine for AIX 中文版:本雜志的内容更加關注于趨勢和企業級架構應用方面的内容,同時對于新興的技術、産品、應用方式等也有很深入的探讨。IBM Systems Magazine 的内容都是由十分資深的業内人士撰寫的,包括 IBM 的合作夥伴、IBM 的主機工程師以及進階管理人員。是以,從這些内容中,您可以了解到更高層次的應用理念,讓您在選擇和應用 IBM 系統時有一個更好的認識。
  • 技術書店:浏覽技術書店,找到這些主題和其他主題的書。

獲得産品和技術

  • 學習更多關于 Boost

    C++

    庫 的知識,找到關于 Boost 安裝的資訊。
  • 學習并下載下傳 Boost Serialization 庫。
  • boostpro

    是現成的 Boost 安裝程式。
  • 免費 試用 IBM 軟體。下載下傳産品試用版,線上登入試用它,在沙箱環境中使用某個産品,或通過雲通路它。從超過 100 個的 IBM 試用産品中進行選擇。

讨論

  • 在 Twitter 上關注 developerWorks。
  • 參與 developerWorks 部落格 并加入 developerWorks 社群。
  • 加入 developerWorks 中文社群。檢視開發人員推動的部落格、論壇、組和維基,并與其他 developerWorks 使用者交流。
  • 加入 AIX 和 UNIX® 論壇:
    • AIX Forum
    • AIX Forum for developers
    • Cluster Systems Management
    • Performance Tools Forum
    • Virtualization Forum
    • 更多的 AIX 和 UNIX 論壇

關于作者

Arpan Sen 是緻力于電子設計自動化行業的軟體開發首席工程師。他使用各種 UNIX 版本(包括 Solaris、SunOS、HP-UX 和 IRIX)以及 Linux 和 Microsoft Windows 已經多年。他熱衷于各種軟體性能優化技術、圖論和并行計算。Arpan 獲得了軟體系統碩士學位。

繼續閱讀