Null终止字符串,它是否真的由标准规定?

时间:2014-07-31 20:47:29

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

讨论

  • 众所周知,从C ++ 11及以后std::basic_string被认为具有空字符终止的内部存储缓冲区。

  • 此更改的主要原因是,std::basic_string的先前定义仅允许对字符串进行非常有限的并发访问,因此对多线程应用程序的性能有限。 (有关std::basic_string更改的原因的更多信息,请参阅proposal N2534)。

  • 但是,阅读标准我找不到明确声明std::basic_string必须有空字符终止内部存储缓冲区的引用。

  • 我发现的唯一隐含引用是§21.4.7.1/ 1& 3 basic_string访问者[string.accessors]:

  
    

const charT* c_str() const noexcept;

         

const charT* data() const noexcept;

         

1返回:指针pp + i == &operator[](i)中每i[0,size()]      3要求:程序不得更改存储在字符数组中的任何值。

  
  • 我认为由于效率原因而且§21.4.7.1/3要求程序不会改变返回的缓冲区,std::basic_string::c_str()std::basic_string::data()中的大多数实现者都返回空字符终止内部缓冲区。

  • 但是,标准没有声明std::basic_string::c_str()std::basic_string::data()必须返回的缓冲区必须是std::basic_string的内部存储缓冲区而不是某些缓冲区空字符终止副本。

问题:

  1. 标准中是否明确声明std::basic_string内部存储缓冲区必须为空字符终止?
  2. 如果没有明确的陈述(即问题#1简答题为否),这是否意味着实施者可以实现std::basic_string而没有空字符终止的内部存储缓冲区,因此宽传播的概念,因为C ++ 11字符串是空终止是错误的?

2 个答案:

答案 0 :(得分:5)

来自 21.4.5

  

const_reference operator[](size_type pos) const; reference operator[](size_type pos);

     

1需要:pos <= size()

     

2返回:   *(begin() + pos)如果pos < size(),则提及T   charT()类型的对象,其值为s[s.size()];参考值应   不被修改。

请注意,NUL定义明确,需要返回NUL字符。

但是,这本身并不需要basic_string - 内部存储。 21.4.1 / 5 有这样的说法:

  

basic_string对象中的char类对象应连续存储。也就是说,对于任何s对象&*(s.begin() + n) == &*s.begin() + nn的所有值都应保留0 <= n < s.size()n < s.size()

请注意,连续存储最多只需要s.size(),但不能用于char* p = &s[0];本身。因此,NUL并不一定指向p[s.size()]终止的缓冲区,因为标准不要求data()有效。

实际上,在c_str()operator[]NUL的要求之间,任何理智的实施都会维持{{1}}终止的存储。但标准似乎并没有排除疯狂的实施。

答案 1 :(得分:1)

在C ++ 11中,c_str()data()都需要返回指向内部存储的指针(对不起,我没有直接引用支持它) 。在早期版本中,c_str()不需要这样做,但是data()是。{1}}。实现者可以(但很少会)实现写时复制语义,以便c_str()返回的指针不是原始的内部存储。

在所有版本中,c_str()都需要返回以null结尾的指针。因此,这意味着在C ++ 11中,内部存储必须以空值终止。