[英]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.