[英]Reliably using C++ Small String Optimization to fread short std::strings from Files into Memory
我有以下類,它包含一個稱為Index的數據結構,它的計算成本很高。 因此,我將索引緩存到磁盤並再次讀入。 模板類型T的索引元素id可以與各種原始數據類型一起使用。
但我也想將id與std :: string類型一起使用。 我為一般情況編寫了序列化/反序列化代碼,並且還測試了它是否適用於普通的C ++字符串,並且是否足夠短(如果它們足夠短的話)。 小字符串優化似乎開始了。
我還寫了一個不同的實現,只是為了安全地處理更長的字符串。 但是安全代碼的速度慢了大約10倍,我真的很想讀入帶有fread的字符串(500ms的讀取非常痛苦,而50ms的情況則非常好)。
如果我知道所有標識符都比最長的短字符串短,那么如何可靠地使用libcpp小字符串優化? 如何可靠地確定最長的小字符串有多長時間?
template<typename T>
class Reader {
public:
struct Index {
T id;
size_t length;
// ... values etc
};
Index* index;
size_t indexTableSize;
void serialize(const char* fileName) {
FILE *file = fopen(fileName, "w+b");
if (file == NULL)
return;
fwrite(&indexTableSize, sizeof(size_t), 1, file);
fwrite(index, sizeof(Index), indexTableSize, file);
fclose(file);
}
void deserialize(const char* fileName) {
FILE *file = fopen(fileName, "rb");
if (file == NULL)
return;
fread(&indexTableSize, sizeof(size_t), 1, file);
index = new Index[indexTableSize];
fread(index, sizeof(Index), indexTableSize, file);
fclose(file);
}
};
// works perfectly fine
template class Reader<int32_t>;
// works perfectly fine for strings shorter than 22 bytes
template class Reader<std::string>;
std::string
是不可復制的 。 並執行memcpy
上的類型(這是相當於fwrite
荷蘭國際集團它和fread
在C ++荷蘭國際集團回)是唯一的合法,如果它是平凡能夠復制。 因此,您想做的事情無法直接實現。
如果要序列化字符串,則必須手動進行。 您必須先獲取字符數並將其寫入,然后再自己寫這些字符。 要讀回它,您必須讀取字符串的大小,然后讀取那么多字符。
如果要使用類型T可靠地進行序列化/反序列化,則必須確保類型T是POD類型(或更准確地說是標准布局和瑣碎的 )。
您可以使用std::is_trivially_copyable<T>
和std::is_standard_layout<T>
在模板中進行檢查。 不幸的是,這對於std::string
將失敗。
如果不是這種情況,則必須找到一種適當的方法來對類進行序列化/反序列化,即,寫入/讀取允許重建對象狀態的數據(此處為字符串的長度及其內容)。
三種選擇:
boost::serialize
, s11n
或其他 無論如何,我都強烈建議您不要依賴非可移植屬性 ,例如短字符串的長度,尤其是如果您的模板中的代碼應與泛型類型一起使用時,尤其如此。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.