48

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

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

4

4 回答 4

43

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

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

它会正常工作。

您基本上可以像对待任何其他动态分配的字符缓冲区一样对待它。您可以上下扫描寻找神奇的数字或模式。您可以部分就地解析它。对于从套接字接收,您可以很容易地调整它的大小以附加更多数据。

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

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

于 2009-01-13T23:02:39.733 回答
8

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

反对字符串的另一个论点是它的名字暗示它包含一个字符串,而不是二进制缓冲区,这可能会使阅读代码的人感到困惑。

也就是说,我也推荐vector。

于 2009-01-14T02:31:17.580 回答
7

我也用std::string这个,从来没有遇到过问题。

一个“指针”,我昨天在一段代码中收到了一个尖锐的提醒:当从一个二进制数据块创建一个字符串时,使用std::string(startIter, endIter)构造函数形式,而不是std::string(ptr, offset, length)形式——后者假设指针指向到 C 风格的字符串,并忽略第一个零字符之后的任何内容(它复制“直到”指定的length,而不是length字符)。

于 2009-01-14T02:10:57.480 回答
3

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

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

关于存储字符的适当 stl 容器的讨论由上面的 Doug 处理。您需要哪一个完全取决于您的用例。如果你只是持有一个你迭代的数据块,没有任何特殊的查找、追加/删除或拼接需求,我更喜欢向量,它比 std::string 更清楚你的意图,许多库和函数都会假设包含一个以 null 结尾的 c 样式字符串。

于 2009-01-14T02:18:18.807 回答