调用“string::c_str()”时实际上做了什么?

Joh*_*ohn 8 c++ string stl

string::c_str()调用时实际上做了什么?

  1. string::c_str()将分配内存,复制字符串对象的内部数据并将空终止字符附加到新分配的内存中?

或者

  1. 由于必须是 O(1),因此不再允许string::c_str()分配内存并复制过来。string实际上,始终存在空终止符是唯一合理的实现。

在这个问题的答案的评论中有人说C++11 要求为尾随std::string分配额外的char'\0'. 所以看来第二种选择是可能的。

另一个人说std::string操作——例如迭代、串联和元素变异——不需要零终止符。除非您将 传递string给需要以零结尾的字符串的函数,否则可以省略它

更多来自专家的声音

为什么实现者通常让 .data() 和 .c_str() 做同样的事情?

因为这样做效率更高。使 .data() 返回非 null 终止的内容的唯一方法是让 .c_str() 或 .data() 复制其内部缓冲区,或者仅使用 2 个缓冲区。拥有一个以 null 结尾的缓冲区始终意味着您在实现 std::string 时始终可以仅使用一个内部缓冲区。

string::c_str()所以我现在真的很困惑,调用时实际上做了什么?

更新

如果c_str()实现为简单地返回指针,则它已经被分配和管理。

A。由于c_str()必须以 null 终止,因此内部缓冲区需要始终以 null 终止,即使对于空的 std::string,例如: ;的内部存储器中std::string demo_str应该有一个。我对吗?\0demo_str

B.std::string::substr()调用时会发生什么自动将 a 添加\0到子字符串中?

Rem*_*eau 13

从 C++11 开始,std::string::c_str()std::string::data()都需要返回指向字符串内部缓冲区的指针。并且由于c_str()(但不是data()) 必须以 null 终止,这实际上要求内部缓冲区始终以 null 终止,尽管 null 终止符不被size()/计数,也不由迭代器等length()返回。std::string

在 C++11 之前, 的行为c_str()在技术上是特定于实现的,但我见过的大多数实现都是以这种方式工作的,因为这是最简单、最明智的实现方式。C++11 只是标准化了已经广泛使用的行为。

更新

从 C++11 开始,缓冲区始终以 null 结尾,即使对于空字符串也是如此。然而,这并不意味着当字符串为空时需要动态分配缓冲区。它可以指向 SSO 缓冲区,甚至指向单个staticnul 字符。无法保证c_str()/返回的指针data()在字符串内容更改时仍指向相同的内存地址。

std::string::substr()返回一个std::string带有自己的空终止缓冲区的新值。从中复制的字符串不受影响。