std :: string是否需要将其字符存储在连续的内存中?

时间:2015-10-14 11:48:29

标签: c++ c++11 c++14 language-lawyer c++17

我知道在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(),但由于显而易见的原因,旧代码不使用它。)

3 个答案:

答案 0 :(得分:27)

C++11 standard,basic_string 21.4.1.5,

  

应存储basic_string对象中类似char的对象   连续。也就是说,对于任何basic_string对象,标识   &amp; *(s.begin()+ n)==&amp; * s.begin()+ n将保留n的所有值   使得0 <= n <0。 s.size()。

答案 1 :(得分:15)

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

  
      
  1. 对于类似char的类型charT,类模板basic_string描述了可以存储的对象   由不同数量的任意类似char的对象组成的序列(第21条)。第一个元素   序列在零位。如果给定的类似char的类型是明确的,则这样的序列也称为“字符串”   从上下文。在本节的其余部分中,charT表示类似于char的类型。存储字符串   由basic_string类的成员函数根据需要分配和释放   Allocator类作为模板参数传递。 Allocator :: value_type应与   图表。
  2.   
  3. 类模板basic_string符合Sequence的要求,如(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字符串库
  4.   
  5. 在所有情况下,size()&lt; = capacity()。
  6.   

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

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

强调我的

所以预先C ++ 17它不能得到保证,但现在却是。

由于std::string::data强加的约束,这种非保证几乎没有用,因为调用std::string::data会给你一个连续的字符串数组。因此,除非实现按需执行此操作,并且在不变的时间内,字符串将是连续的。

  

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

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

  

返回:如果pos&lt; size(),返回data()[pos]。否则,如果pos == size(),则为const   version返回charT()。否则,行为未定义。

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

  

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

因此,如果您const为空时尝试const&s[0]和非s版本都会定义行为。

答案 2 :(得分:2)

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

  

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