首页 > 解决方案 > 为什么 C++11 使 std::string::data() 添加一个空终止字符?

问题描述

以前这是std::string::c_str()' 的工作,但从 C++11 开始,data()也提供了它,为什么将c_str()' 的空终止字符添加到std::string::data()?对我来说,这似乎是在浪费 CPU 周期,在 null 终止字符根本不相关且仅data()使用的情况下,C++03 编译器不必关心终止符,也不需要每次调整字符串大小时都必须向终止符写入 0,但是由于data()-null 保证,C++11 编译器必须在每次调整字符串大小时浪费循环写入 0,因此它可能会使代码变慢,我想他们有理由添加那个保证,那是什么?

标签: c++stringc++11stdstringc++03

解决方案


这里有两点要讨论:

空终止符的空间

理论上,C++03 实现可以避免为终止符分配空间和/或可能需要执行复制(例如unsharing)。

但是,所有理智的实现都为空终止符分配了空间以支持c_str()开始,因为否则如果这不是一个微不足道的调用,它将几乎无法使用。

空终止符本身

确实,一些非常(1999)、非常古老的实现(2001)编写了\0每次c_str()调用。

然而,在 C++11 发布之前,主要实现发生了变化(2004 年)或已经改变了(2010 年),以避免这种事情发生,所以当新标准到来时,对于许多用户来说,什么都没有改变。

现在,无论 C++03 实现是否应该这样做:

对我来说,这似乎是在浪费 CPU 周期

并不真地。如果您c_str()不止一次调用,那么您已经通过多次编写而浪费了周期。不仅如此,您还弄乱了缓存层次结构,这在多线程系统中很重要。回想一下,多核/SMT CPU 开始出现在2001 年2006 年之间,这解释了向现代非 CoW 实现的转变(即使在那之前的几十年里有多 CPU 系统)。

唯一可以保存任何东西的情况是,如果您从未调用过c_str(). 但是,请注意,当您重新调整字符串的大小时,无论如何您都在重新编写所有内容。一个额外的字节将很难测量。

换句话说,如果没有在重新调整大小时编写终结符,您将自己暴露在更差的性能/延迟中。通过同时编写一次,您必须执行字符串的副本,性能行为更加可预测,并且如果您最终使用 ,您可以避免性能缺陷c_str(),特别是在多线程系统上。


推荐阅读