在c + + 11中string :: c_str()不再是空的吗?
在C ++ 11中, basic_string::c_str
被定义为与basic_string::data
完全相同,这又被定义为与*(begin() + n)
和*(&*begin() + n)
(当0 <= n < size()
)时。
我找不到任何需要string在其末尾始终为空的字符。
这是否意味着c_str()
不再保证产生一个以null结尾的string?
string现在需要在内部使用空终止的缓冲区。 看operator[]
(21.4.5)的定义:
需要:
pos <= size()
。如果
pos < size()
,则返回*(begin() + pos)
,否则返回值为charT()
T
types对象的引用。 参考值不得修改。
回顾c_str
(21.4.7.1/1),我们看到它是用operator[]
来定义的:
返回:对于
[0,size()]
每个i
,指针p
使得p + i == &operator[](i)
。
而且c_str
和data
都要求为O(1),所以实现被迫使用null终止的缓冲区。
另外,正如DavidRodríguez在注释中指出的那样,返回值的要求也意味着你可以使用&operator[](0)
作为c_str()
的同义词,所以终止空字符必须位于同一个缓冲区*(p + size())
必须等于charT()
); 这也意味着,即使终止者被懒惰地初始化,也不可能观察处于中间状态的缓冲区。
那实际上,新标准确实规定.data()和.c_str()现在是同义词。 但是,并不是说.c_str()不再是零终止:)
这只是意味着你现在可以依靠.data()被零终止。
第N2668号文件定义了std :: basic_string的c_str()和data()成员,如下所示:
const charT* c_str() const; const charT* data() const;
返回:指向长度为size()+ 1的数组的初始元素的指针,该数组的第一个size()元素等于由* this控制的string的相应元素,其最后一个元素是由charT()指定的空字符。
要求:程序不应该改变存储在字符数组中的任何值。
请注意,这并不意味着任何有效的std :: string可以被视为一个Cstring,因为std :: string可以包含embedded的空值,当直接用作const char *时,它会过早地结束Cstring。
附录:
我没有访问C ++ 11的实际发布的最终规范,但似乎确实在该规范的修订历史logging中某处放弃了措辞:例如http://www.open-std.org/jtc1/ SC22 / WG21 /文档/文件/ 2011 / n3242.pdf
§21.4.7 basic_stringstring操作
[string.ops]
§21.4.7.1 basic_string访问器
[string.accessors]
const charT* c_str() const noexcept; const charT* data() const noexcept;
- 返回:对于
[0,size()]
每个i
,指针p使得p + i == &operator[](i)
。- 复杂性:不变的时间。
- 要求:程序不应该改变存储在字符数组中的任何值。
“历史”是很久以前,每个人都在单线程中工作,或者至less线程是拥有自己数据的工作者,他们为C ++devise了一个string类,这使得string处理比以前更容易,并且它们被重载运算符+来连接string。
问题是用户会做这样的事情:
s = s1 + s2 + s3 + s4;
并且每个连接都会创build一个临时实现一个string。
因此,有人有“懒惰的评价”的脑波,这样在内部你可以存储某种“绳索”与所有的string,直到有人想读它作为一个Cstring,在这一点上,你会改变内部表示为一个连续的缓冲区。
这解决了上述问题,但是却导致了一些其他的烦恼,特别是在multithreading世界中,一个预期.c_str()操作是只读的/不会改变任何东西,因此不需要locking任何东西。 过早的内部locking在类实现中,以防万一有人在multithreading的情况下(甚至没有线程标准)也不是一个好主意。 事实上,做任何事情都比每次简单复制缓冲区都要昂贵。 同样的原因“拷贝写入”实现被放弃了string实现。
因此,使.c_str()
成为一个真正不可变的操作是最明智的做法,然而,如果一个标准现在是线程感知的,那么它可以“依赖”它吗? 因此,新标准决定明确表示可以,因此内部表示需要保留空终止符。
发现得好。 这在最近通过的标准中肯定是一个缺陷。 我敢肯定,目前没有意图打破目前使用c_str
所有代码。 我会提出一个缺陷报告,或者至less在comp.std.c++
提出这个问题(如果问题涉及缺陷的话,通常会在委员会面前结束)。