亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何在C+中序列化對象?

如何在C+中序列化對象?

C++
青春有我 2019-07-13 10:43:00
我有一個小的對象層次結構,我需要通過套接字連接來序列化和傳輸這些對象。我需要同時序列化對象,然后根據對象的類型反序列化它。在C+中是否有一種簡單的方法(就像在Java中那樣)?是否有任何C+序列化聯機代碼示例或教程?編輯:為了明確起見,我正在尋找將對象轉換為字節數組的方法,然后再將其轉換為對象。我能處理插座傳輸。
查看完整描述

3 回答

?
婷婷同學_

TA貢獻1844條經驗 獲得超8個贊

在某些情況下,在處理簡單類型時,可以:

object o;socket.write(&o, sizeof(o));

這可以作為概念的證明或初稿,這樣你的團隊中的其他成員就可以繼續在其他部分工作。

但遲早通常更早這會讓你受傷的!

你會遇到以下問題:

  • 虛擬指針表將被破壞。
  • 指針(指向數據/成員/函數)將被破壞。
  • 不同機器上填充/對齊的差異。
  • 大/小字節排序問題。
  • 浮動/雙倍實現的變化。

(另外,你需要知道在接收方你要打開什么。)

您可以通過為每個類開發自己的編組/解編組方法來改進這一點。(理想情況下是虛擬的,因此可以在子類中擴展它們。)一些簡單的宏將允許您以大/小-端中性的順序相當快地寫出不同的基本類型。

但這種粗制濫造的工作要好得多,而且更容易,通過Boost序列化庫.


查看完整回答
反對 回復 2019-07-13
?
慕碼人2483693

TA貢獻1860條經驗 獲得超9個贊

序列化意味著將對象轉換為二進制數據。反序列化意味著從數據重新創建對象。

序列化時,您將字節推入uint8_t矢量。取消序列化時,您將從uint8_t矢量。

當然,在序列化東西時可以使用一些模式。

每個可序列化的類都應該有一個serialize(std::vector<uint8_t> &binaryData)或類似的簽名函數,將其二進制表示寫入所提供的向量。然后,這個函數可以將這個向量傳遞給它的成員的序列化函數,這樣他們也可以將它們的內容寫入其中。

因為數據表示在不同的體系結構上可能是不同的。您需要找出如何表示數據的方案。

讓我們從基礎開始:

序列化整數數據

只需按小Endian順序寫字節即可。如果尺寸重要,也可以使用varint表示。

按小端點順序序列化:

data.push_back(integer32 & 0xFF);data.push_back((integer32 >> 8) & 0xFF);data.push_back((integer32 >> 16) & 0xFF);data.push_back((integer32 >> 24) & 0xFF);

從小端序反序列化:

integer32 = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);

序列化浮點數據

據我所知,IEEE 754在這里擁有壟斷地位。我不知道有什么主流建筑會用別的東西來做浮標。唯一不同的是字節順序。一些體系結構使用小Endian,另一些使用大Endian字節順序。這意味著您需要小心哪種順序大聲地向您發出接收端的字節。另一個不同之處是處理非正態值、無窮大值和NaN值。但是,只要你避免這些值,你就應該沒事。

序列化:

uint8_t mem[8];memcpy(mem, doubleValue, 8);data.push_back(mem[0]);data.push_back(mem[1]);...

反序列化是向后執行。注意架構的字節順序!

序列化字符串

首先,您需要就編碼達成一致。烏特夫-8是很常見的。然后以長度前綴的方式存儲它:首先使用我前面提到的方法存儲字符串的長度,然后逐字節編寫字符串。

序列化數組。

它們和字符串是一樣的。首先序列化表示數組大小的整數,然后序列化數組中的每個對象。

序列化整個對象

就像我之前說的,他們應該有一個serialize方法,該方法向量添加內容。要取消對象的序列化,它應該有一個接受字節流的構造函數。它可以是istream但在最簡單的情況下,它只是一個參考uint8_t指針。構造函數從流中讀取它想要的字節,并在對象中設置字段。如果系統設計良好并按對象字段順序序列化字段,則只需將流傳遞給初始化程序列表中的字段構造函數,并按正確的順序反序列化。

序列化對象圖

首先,您需要確保這些對象是否確實是要序列化的對象。如果目標上存在這些對象的實例,則不需要序列化它們。

現在,您發現需要序列化指針所指向的對象。指針僅在使用它們的程序中有效的問題。不能序列化指針,應停止在對象中使用指針。相反,創建對象池。這個對象池基本上是一個包含“方框”的動態數組。這些框有參考計數。非零引用計數表示活動對象,零表示空槽.然后創建與Shared_PTR類似的智能指針,該指針不存儲指向對象的指針,而是存儲在數組中的索引。您還需要就表示空指針的索引達成一致,例如。-1。

基本上,我們在這里所做的是用數組索引替換指針?,F在,當序列化時,您可以像往常一樣序列化這個數組索引。您不需要擔心對象在目標系統的內存中的位置。確保他們也有相同的對象池。

所以我們需要序列化對象池。但是哪一個呢?那么,當您序列化對象圖時,您并不只是序列化一個對象,而是序列化整個系統。這意味著系統的序列化不應該從系統的各個部分開始。這些對象不應該擔心系統的其他部分,它們只需要序列化數組索引,僅此而已。您應該有一個系統序列化程序例程,該例程負責編排系統的序列化,并遍歷相關的對象池并序列化所有對象池。

在接收端,所有對象中的數組都被反序列化,重新創建所需的對象圖。

序列化函數指針

不要在對象中存儲指針。有一個靜態數組,其中包含指向這些函數的指針,并將索引存儲在對象中。

因為這兩個程序都將這個表編譯到了書架上,所以只使用索引就可以了。

序列化多態類型

由于我說過您應該避免序列化類型中的指針,并且應該使用數組索引,所以多態不能工作,因為它需要指針。

您需要使用類型標記和聯合來解決這個問題。

版本化

最重要的是。您可能需要不同版本的軟件互操作。

在這種情況下,每個對象都應該在序列化開始時寫入版本號,以指示版本。

當在另一邊加載對象時,較新的對象可能能夠處理舊的表示,但舊的對象不能處理新的表示,因此它們應該拋出一個異常。

每當某件事情發生變化時,您都應該增加版本號。


因此,要總結這一點,序列化可能很復雜。但幸運的是,您不需要序列化程序中的所有內容,大多數情況下,只有協議消息被序列化,這通常是普通的舊結構。所以你不需要我經常提到的復雜技巧。


查看完整回答
反對 回復 2019-07-13
  • 3 回答
  • 0 關注
  • 393 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號