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

101*_*010 4 c++ stdstring language-lawyer c++11 c++14

讨论

  • 众所周知,从C++ 11开始,std::basic_strings被认为具有空字符终止的内部存储缓冲区.

  • 除其他之外,这种变化的主要原因是之前的定义std::basic_string只允许对字符串进行非常有限的并发访问,因此对多线程应用程序的性能有限.(有关更改原因的更多信息,请std::basic_string参阅提案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返回:一个指针p,p + i == &operator[](i)用于每个iin [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以来的广泛传播概念字符串是null终止是错误的?

Igo*_*nik 5

21.4.5开始:

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

1要求:pos <= size().

2返回: *(begin() + pos)if pos < size(),否则引用T具有值的类型的对象charT(); 参考值不得修改.

请注意,它s[s.size()]是明确定义的并且需要返回NUL字符.

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

basic_string对象中的char类对象应连续存储.也就是说,任何basic_string对象s,身份&*(s.begin() + n) == &*s.begin() + n应持的所有值n这样0 <= n < s.size().

请注意,连续存储仅需要最多n < s.size(),但不是s.size()自身.因此char* p = &s[0];,不一定指向NUL终止缓冲区,因为标准不要求p[s.size()]有效.

实事求是地讲,需求之间的data(),c_str()并且operator[],任何理智的实施将保持NUL封端的存储.但标准似乎并没有排除疯狂的实施.

  • 但是这个引用并不要求内部存储本身是空终止的,只要它要求`[]`在请求`<size()`时返回对内部存储的引用,否则引用null字符.这不需要null来自内部存储,它可能来自内部常量文字(这是`c_str()`通常返回指向`size()`为0时的指针.在这句话中,没有什么要求`s [s.size() - 1]`和`s [s.size()]`来返回内存中连续数据的引用. (2认同)