将std::string转换为C++字节数组

18

Google的Protocol Buffer使用C++标准字符串类std::string作为可变大小的字节数组(请参见此处),类似于Python中字符串类也被用作字节数组(至少在Python 3.0之前是这样)。

这种方法似乎很好:

  • 它允许通过assign快速赋值和通过data进行快速直接访问,而使用vector<byte>则不允许
  • 与使用byte*相比,它允许更容易的内存管理和const引用。

但我很好奇:这是C++中字节数组的首选方式吗?这种方法有哪些缺点(比一些static_cast多)?


1
你忘了:* 如果你的变量字节数组确实是一个字符串,那么字符串类会给你有用的字符串方法,比如find(),而std::vector则没有。 (对于std::vector,你需要引入<algorithms>或类似的库。) - Mike DeSimone
3个回答

8

就我个人而言,我更喜欢使用 std::vector,因为不能保证 std::string 存储在连续的内存空间中,而且 std::string::data() 不一定是 O(1) 的。在 C++0x 中,std::vector 将有 data 成员函数。


1
即使没有 std::vector::data(),你也可以通过 &v[0](确保它不为空)获得相同的结果。 - Mike Seymour
你可以通过调用 std::stringc_str() 方法来强制其存储连续的内存。虽然有些粗糙,但是很有效。这样做可以在需要时强制使用连续的内存。 - Mike DeSimone
Mike,data()c_str()更适合这里,因为它不会附加终止0。后者甚至可能比前者更慢。 - avakar
@Mike:不,c_str()强制字符串给你一个连续的表示,但这并不强制它“存储连续”。关键在于data()c_str()不会使迭代器或引用失效,因此实现不能“丢弃”之前使用的任何非连续存储。修改从c_str()data()返回的数组是未定义行为,而对于向量,您可以修改从&v[0]获取的数组,并且它会修改向量。这是一堆老古董,没有人实现非连续的字符串,这就是为什么C++0x正在改变它的原因;-) - Steve Jessop
不,关于“线索”的那部分删掉。SGI原始STL和标准之间有区别,我看的是STL。data()c_str()可能会使引用失效。但这仍然不意味着它们需要转换字符串的“真实”存储方式。它们都返回const char*,所以与向量不同,标准并不要求字符串提供任何提供连续可修改数据的方法。这就是你需要使用C风格读取API的情况。 - Steve Jessop

3
可能具有引用计数实现,这可能是优势/劣势,具体取决于您编写的内容--请务必小心。 可能不是线程安全的。 的潜在优势是易于连接,但是这也可以使用STL轻松实现。
此外,使用及其缓冲对象时,与协议相关的所有这些问题都会消失。
至于的缺点:
1.可以通过使用< std::swap>技巧快速分配
2.数据可以通过&arr [0]访问--向量保证(?)连续(至少所有实现都这样实现)
个人而言,我使用来处理可变大小的数组,并使用来处理静态大小的数组。

1
请注意,仅当向量包含至少一个元素时,&arr[0]的行为才被定义。 - avakar
2
std::vector(实际上)保证不会被引用计数 - 但这并不使它比std::string更线程安全。 - anon
@Niel,我们在服务器上工作时因为GCC的字符串线程不安全而经历了一番煎熬。转换为向量确实有所帮助。 - Kornel Kisielewicz
1
多线程访问是线程安全的关键所在 - 如果只有一个线程,那么保证线程安全就很容易! - anon
1
@Neil,字符串实现可能会在没有适当锁定的情况下修改共享状态。好的,问题应该是:只要我不从多个线程访问/修改同一实例,而是同时访问其他std :: string实例,那么std :: string是否是线程安全的? - dmeister
显示剩余5条评论

2

我认为使用std::vector是更好的选择,因为它被设计用作数组。虽然所有实现(我知道和听说的)都将字符串“元素”存储在连续的内存中,但这并不意味着它是标准的。也就是说,像字节数组一样使用std::string的代码假定元素是连续的,而根据标准,它们不必是连续的。


在最初的C++标准中,std::vector并不要求连续存储,但是2003年的标准确实要求它(§23.2.4/1)。C++ 0x将为std::string添加类似的要求(N3000中的§[string.require]/5)。 - Jerry Coffin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接