使用C ++ / STL存储二进制数据的“正确”方法

时间:2009-01-13 22:58:12

标签: c++ stl binary-data

一般来说,在C ++中存储二进制数据的最佳方法是什么?据我所知,这些选项很大程度上归结为使用字符串或向量< char> s。 (我将省略char * s和malloc()的可能性,因为我指的是C ++)。

通常我只是使用一个字符串,但是我不确定是否存在我缺少的开销,或者STL在内部进行的转换可能会破坏二进制数据的完整性。有没有人对此有任何指针(har)?这样或那样的建议或偏好?

4 个答案:

答案 0 :(得分:40)

char的向量很好,因为内存是连续的。因此,您可以将它与许多C API一起使用,例如berkley套接字或文件API。您可以执行以下操作,例如:

  std::vector<char> vect;
  ...
  send(sock, &vect[0], vect.size());

它会正常工作。

你可以像处理任何其他动态分配的char缓冲区一样对待它。您可以上下扫描寻找神奇的数字或图案。您可以部分解析它。要从套接字接收,您可以非常轻松地调整它以附加更多数据。

缺点是调整大小并不是非常有效(谨慎调整大小或预分配),并且从数组前面删除也将非常缺乏。例如,如果您需要经常在数据结构前面一次只弹出一个或两个字符,则可以选择在此处理之前复制到双端队列。这会使您复制并且双端队列内存不是连续的,因此您不能只是将指针传递给C API。

最重要的是,在潜入之前了解数据结构及其权衡,但是char的向量通常是我在一般实践中使用的。

答案 1 :(得分:8)

std :: string的最大问题是当前标准不保证其底层存储是连续的。但是,没有已知的STL实现,其中string不是连续的,因此在实践中它可能不会失败。事实上,新的C ++ 0x标准将通过强制std :: string使用连续缓冲区来解决这个问题,例如std :: vector。

针对字符串的另一个参数是它的名字表明它包含一个字符串,而不是一个二进制缓冲区,这可能会引起混淆读取代码的人。

那就是说,我也推荐矢量。

答案 2 :(得分:6)

我也使用std::string,并且从未遇到任何问题。

一个“指针”,我刚刚在昨天的一段代码中提醒了一下:当从二进制数据块创建字符串时,使用std::string(startIter, endIter)构造函数表单,而不是{{1} } form - 后者假设指针指向C风格的字符串,并忽略第一个零字符后的任何内容(它复制“最多”指定的std::string(ptr, offset, length),而不是length个字符)。

答案 3 :(得分:3)

你当然应该使用一些char容器,但你想要使用的容器取决于你的应用程序。

Chars有几个属性可以使它们对于保存二进制数据很有用:标准不允许对char数据类型进行任何“填充”,这很重要,因为这意味着你不会在二进制布局中获得垃圾。每个char也保证恰好是一个字节,使其成为唯一具有设置宽度的普通旧数据类型(POD)(所有其他数据类型都根据上限和/或下限指定)。

关于用于存储字符的适当stl容器的讨论由Doug在上面处理。您需要哪一个完全取决于您的用例。如果您只是持有一个数据块而无需任何特殊查找,追加/删除或拼接需求,我宁愿使用vector,这使得您的意图比std :: string更清晰,许多库和函数都会假设保存以null结尾的c样式字符串。