std::string 与字节缓冲区(c++ 中的差异)

Posted

技术标签:

【中文标题】std::string 与字节缓冲区(c++ 中的差异)【英文标题】:std::string vs. byte buffer (difference in c++) 【发布时间】:2017-05-24 18:38:25 【问题描述】:

我有一个项目,我使用 boost.asio 套接字在客户端和服务器之间传输数据。一旦连接的一侧接收到数据,它将其转换为std::strings 的std::vector,然后通过先前定义的“回调”函数传递给数据的实际接收对象。到目前为止,这种方式工作得很好,只是,我现在使用atoi()to_string 之类的方法将字符串以外的其他数据类型转换为可发送格式并返回。这种方法在网络使用方面当然有点浪费(尤其是在传输比单个整数和浮点数更大的数据时)。因此我想序列化和反序列化数据。因为,实际上,任何序列化方法都会产生一个字节数组或缓冲区,所以我只使用std::string 会很方便。这样做有什么缺点吗?我不明白为什么应该有一次,因为字符串应该只是字节数组。

【问题讨论】:

“这样做有什么缺点吗?” 没有。也许std::vector<uint8_t> 在语义上可能更清晰。 std::string 据我所知,几乎必须终止其缓冲区,而 std::vector<char> 则不必。不过,与std::string 提供的额外功能相比,可能不足以担心性能影响。 @DanielSchepler 我认为std::string 不是空终止的,只有string::c_strstring::data 给你一个空终止序列 但是string::c_str 至少在 cppreference.com 被记录为恒定时间,除了在其后使用空终止符维护字符串数据之外,我不知道您将如何实现这一点。 【参考方案1】:

就功能而言,没有真正的区别。

但是,出于性能原因和代码清晰的原因,我建议改用 std::vector<uint8_t>,因为它使维护代码的任何人都更清楚它是字节序列,而不是字符串。

【讨论】:

【参考方案2】:

处理字符串时应该使用std::string,处理二进制blob时最好使用std::vector<uint8_t>。有很多好处:

您的意图很明确,因此代码不易出错

您不会将二进制缓冲区作为字符串传递给错误地期望 std::string 的函数

您可以覆盖 std::ostream<<() 以使用正确的格式(通常是十六进制转储)打印此类型的 blob。您不太可能希望将二进制 blob 打印为字符串。

可能还有更多。 std::string 的唯一好处是我可以看到您不需要执行 typedef。

【讨论】:

【参考方案3】:

你是对的。字符串只不过是字节数组。 std::string 只是一种管理表示字符串的缓冲区数组的便捷方式。就是这样!

使用std::string 没有任何缺点,除非您正在处理对性能非常关键的东西,例如内核……然后使用std::string 会产生相当大的开销。除此之外,请随意使用。

--

幕后的std::string 需要对字符串的状态进行一系列检查,以确定是否使用小字符串优化。今天几乎所有的编译器都实现了小字符串优化。它们都使用不同的技术,但基本上它需要测试位标志,以判断字符串是在堆栈中还是在堆中构造。如果您直接使用char[],则不存在此开销。但同样,除非您正在处理非常关键的东西,例如内核,否则您不会注意到任何东西,std::string 更方便。

同样,这只是幕后发生的事情之一,只是作为一个例子来展示它们的区别。

【讨论】:

是的,如果你在内核级别使用std::string,开销是非常可观的。这是一个例子......但还有更多:***.com/questions/21946447/… @Ðаn 我个人不知道细节,但std::string 有少量额外开销,因为它需要遵守几个约束,包括但不限于以下事实它需要始终分配一个额外的字节来以空值终止字符串。但与此同时,std::string 对象可以进行“小字符串优化”,这可以改善内存占用。要带走的关键点是std::string 可以在幕后做一些你可能没想到的事情。 @Xirema,关于空终止字符,C-String 和std::string 都有。所以这不是问题。开销与构造和删除字符串所需的代码有关。例如,它需要处理小字符串优化等情况……这使得std::string 有点沉重!我会用详细信息更新答案。 @WagnerPatriota 我们不是在比较std::string 和“C-Strings”,而是比较std::stringchar[]std::vector<char>char[]std::vector<char>不自动分配和管理空终止符;它需要由用户手动添加(或者更有可能被忽略,因为没有好的字符串使用依赖于它)。 @Ðаn 好吧,我不知道所有细节。我只知道有各种影响std::string 的事情std::vector 很乐意忽略,这会对性能产生影响。【参考方案4】:

根据您发送网络消息的频率,std::string 应该没问题。这是一个为您处理大量char 工作的便利类。但是,如果您有大量数据要推送,那么直接使用 char 数组并将其转换为字节可能是值得的,以尽量减少 std::string 的额外开销。

编辑:如果有人可以评论并指出您认为我的答案不好的原因,那就太好了,也可以帮助我学习。

【讨论】:

以上是关于std::string 与字节缓冲区(c++ 中的差异)的主要内容,如果未能解决你的问题,请参考以下文章

C++ std::string::size()函数(返回字符串的长度,以字节为单位)(与std::string::length()函数相同)

如何将超过 65536 字节的二进制数据编码为 c++ 上的 websocket 帧

与静态库中的 std::string 相关的 C++ 未定义符号

C++ 中的 StringStream/c_str() 损坏

c# string与c++ std::string的互相转换

c# string与c++ std::string的互相转换