簡體   English   中英

Google協議緩沖區和std :: string用於任意二進制數據

[英]Google protocol buffers and use of std::string for arbitrary binary data

相關問題: 向量<unsigned char> vs二進制數據字符串

我的代碼將vector<unsigned char>用於任意二進制數據。 但是,我的許多代碼都必須與Google的協議緩沖區代碼交互。 協議緩沖區將std::string用於任意二進制數據。 這造成了很多丑陋的分配/復制/空閑周期,只是在Google協議緩沖區和我的代碼之間移動數據。 在很多情況下,我需要兩個構造函數(一個構造函數需要一個向量,一個構造函數需要一個字符串)或兩個函數將一個函數轉換為二進制有線格式。

該代碼在內部處理了很多原始結構,因為結構是內容可尋址的(通過哈希存儲和檢索),已簽名等。 因此,這不僅僅是與Google協議緩沖區的接口有關的問題。 對象也以原始形式在代碼的其他部分處理。

我可以做的一件事就是將我的所有代碼剪切成將std::string用於任意二進制數據。 我可以做的另一件事是嘗試找出更有效的方法來將向量存儲和檢索到Google協議緩沖區對象中。 我猜我的另一選擇是創建標准,簡單但緩慢的字符串轉換函數並始終使用它們。 這樣可以避免猖code的代碼重復,但是從性能的角度來看將是最糟糕的。

有什么建議么? 還有什么更好的選擇?

這就是我要避免的事情:

if(SomeCase)
{
    std::vector<unsigned char> rawObject(objectdata().size());
    memcpy(&rawObject.front(), objectdata().data(), objectdata().size());
    DoSometingWith(rawObject);
}

當原始數據已經存在時,分配,復制,處理,釋放是完全沒有意義的。

有兩種避免復制的方法,我知道並已經在使用中。

實際上,傳統方式確實是將指針/引用傳遞給已知實體。 盡管這可以很好地工作並且大驚小怪,但問題是,它將您與給定的表示形式聯系在一起,這需要在必要時進行轉換(根據您的經驗)。

我用LLVM發現的另一種方法是:

這個想法非常簡單:都持有一個指向T數組開頭的T*和一個指示元素數量的size_t

神奇的是它們完全隱藏了實際的存儲,無論是stringvector ,動態還是靜態分配的C數組……都沒有關系。 呈現的界面是完全統一的,不涉及任何副本。

唯一的警告是它們擁有內存的所有權( Ref !),因此如果您不小心,可能會潛入一些細微的錯誤。 不過,如果只在瞬態操作中使用它們(例如,在函數內),並且不存儲它們以備后用,通常還是可以的。

我發現它們在緩沖區操作中非常方便,尤其是由於有了免費的切片操作。 范圍比成對的迭代器要容易得多。


我還經歷了第三種方法,但是直到現在還沒有在嚴肅的代碼中使用過。 這個想法是vector<unsigned char>是非常底層的表示。 通過提高抽象層並使用Buffer類,您可以完全封裝內存的確切存儲方式,從而就您的代碼而言,它成為非問題。

然后,隨意選擇一種需要較少轉換的內存表示形式。

為避免使用此代碼(您提供的代碼),

if(SomeCase)
{
    std::vector<unsigned char> rawObject(objectdata().size());
    memcpy(&rawObject.front(), objectdata().data(), objectdata().size());
    DoSometingWith(rawObject);
}

假設objectDatastd::string ,請考慮

typedef unsigned char      Byte;
typedef std::vector<Byte>  ByteVector;

然后例如

if( someCase )
{
    auto const& s = objectData;
    doSomethingWith( ByteVector( s.begin(), s.end() ) );
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM