24

我知道在 C++98 中,既不需要std::basic_string<>也不std::vector<>需要使用连续存储。std::vector<>一旦被指出,这被视为疏忽,而且,如果我没记错的话,用 C++03 修复了。

似乎记得在 C++11 仍被称为 C++0x 时,我曾读过关于需要std::basic_string<>使用连续存储的讨论,但当时我并没有密切关注讨论,并且在工作中仍然仅限于 C++03 ,所以我不确定它是怎么回事。

那么std::basic_string<>需要使用连续存储吗?(如果是这样,那么哪个版本的标准首先需要它?)

如果您想知道:如果您有代码将结果传递&str[0]给期望写入连续内存的函数,这一点很重要。(我知道str.data(),但由于明显的原因旧代码不使用它。)

4

3 回答 3

29

C++11 标准,basic_string 21.4.1.5,

basic_string 对象中的类字符对象应连续存储。也就是说,对于任何 basic_string 对象 s,标识 &*(s.begin() + n) == &*s.begin() + n 应适用于所有 n 值,使得 0 <= n < s.size ()。

于 2015-10-14T11:52:31.863 回答
15

在 c++03 中,不能保证字符串的元素是连续存储的。[basic.string] 是

  1. 对于 char-like 类型 charT,类模板 basic_string 描述了可以存储由不同数量的任意 char-like 对象组成的序列的对象(第 21 条)。序列的第一个元素位于零位置。如果给定的类似 char 的类型在上下文中是明确的,那么这样的序列也称为“字符串”。在本节的其余部分,charT 表示这种给定的类似 char 的类型。字符串的存储空间由 basic_string 类的成员函数通过作为模板参数传递的分配器类根据需要分配和释放。Allocator::value_type 应与 charT 相同。
  2. 类模板 basic_string 符合 (23.1.1) 中指定的序列的要求。此外,由于 basic_string 支持的迭代器是随机访问迭代器 (24.1.5),因此 basic_string 符合 (23.1) 中指定的可逆容器的要求。389 ISO/IEC 14882:2003(E)  ISO/IEC 21.3 类模板 basic_string 21 字符串库
  3. 在所有情况下,size() <= capacity()。

然后在 C++17 中他们也改变了它

  1. 类模板 basic_string 描述了可以存储由不同数量的任意 char 类对象组成的序列的对象,该序列的第一个元素位于零位置。如果从上下文中可以清楚地看出它所包含的类字符对象的类型,那么这样的序列也称为“字符串”。在本条款的其余部分中,保存在 basic_string 对象中的类 char 对象的类型由 charT 指定。
  2. basic_string 的成员函数使用作为模板参数传递的 Allocator 类的对象来为所包含的 char 类对象分配和释放存储空间。 233
  3. basic_string 是一个连续的容器 (23.2.1)。
  4. 在所有情况下,size() <= capacity()。

强调我的

所以在 C++17 之前,它并不能保证,但现在可以了。

由于std::string::data施加这种不保证的约束几乎没有实际意义,因为调用std::string::data为您提供了字符串中字符的连续数组。因此,除非实现是按需执行此操作并且在恒定时间内字符串将是连续的。


如果您想知道:如果您有代码将结果传递&str[0]给期望写入连续内存的函数,这一点很重要。(我知道str.data(),但由于明显的原因旧代码不使用它。)

的行为operator[]也发生了变化。在 C++03 中,我们有

返回:如果 pos < size(),则返回 data()[pos]。否则,如果 pos == size(),则 const 版本返回 charT()。否则,行为未定义。

因此,const如果您尝试&s[0]何时s为空,则只能保证该版本具​​有定义的行为。在 C++11 中,他们将其更改为:

返回: *(begin() + pos) 如果 pos < size()。否则,返回对具有值 charT() 的 charT 类型对象的引用,其中修改对象会导致未定义的行为。

因此,如果您尝试何时为空,那么现在const和非版本都已定义行为。const&s[0]s

于 2015-10-14T12:02:23.020 回答
2

根据草案标准N4527 21.4/3 类模板 basic_string [basic.string]

basic_string 是一个连续的容器 (23.2.1)。

于 2015-10-14T11:52:59.600 回答