众所周知,从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
返回:指针p
,p + 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
的内部存储缓冲区而不是某些缓冲区空字符终止副本。
std::basic_string
内部存储缓冲区必须为空字符终止?std::basic_string
而没有空字符终止的内部存储缓冲区,因此宽传播的概念,因为C ++ 11字符串是空终止是错误的? 答案 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() + n
,n
的所有值都应保留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中,内部存储必须以空值终止。