默认构造的std::string c_str()值

3
std::string s1;
std::string s2;
assert(strlen(s1.c_str()) == 0);
assert(s1.c_str() == s2.c_str());

这两个断言总是成立吗?
我使用C++11,并检查了标准,第21.4.2节的表格63中说:
data()是可复制且可以添加0的非空指针 size()为0 capacity()是未指定的值
我认为c_str()data()相同。但是我对此定义有些疑问。
1. "CAN have 0 added to it" == "MUST and ALWAYS have 0 added to it"是否相等? 2. 所有默认构造的std::string共享同一个底层缓冲区吗?
我在gcc上测试,这两个断言都为真。我想知道这对于所有编译器是否始终如此?

1
你使用的GCC版本和编译选项是什么?在GCC/libstdc++中,自C++11以来实现了SSO,因此第二个assert应该为false。Clang/libc++和MSVC也是如此。在线演示:https://godbolt.org/z/7zj5bdT9v。 - Daniel Langr
1
@DanielLangr 我不确定默认设置是什么,但libstdc++有一个配置开关,决定是否对空字符串使用共享静态对象,我记得以前看到过一些问题:--enable-fully-dynamic-string,请参见https://gcc.gnu.org/onlinedocs/libstdc++/manual/configure.html。 - user17732522
1个回答

5

第一个断言保证成功。 c_str() 总是返回指向以空字符结尾的字符串的指针,其字符串内容与 std::string 对象持有的相同,对于两个 s1 都是空字符串。

第二个断言不保证成功。没有要求从 std::string 返回的 c_str() 如果内容相同,则必须相同。默认构造的字符串不需要共享相同的底层缓冲区。这将是特定标准库实现的实现细节。(我认为 libstdc++ 根据配置原因在某些情况下执行此操作以实现向后兼容性?如果我记得正确,可以查看 --enable-fully-dynamic-string configure 选项)。

请注意,在C++11之前,data()c_str()的效果不同。 data()不能保证提供指向以空字符结尾的字符串的指针。如果字符串为空,则不允许解引用由其返回的指针。因此,在C++11之前,在示例中将c_str()替换为data()会导致对调用strlen的未定义行为。
"并且可以将0添加到其中"这个措辞有些奇怪,我不完全确定它想要传达什么意思,但对于C++11(草案N3337),data()的返回值在[string.accessors]/1中进一步指定,以便对于范围内的所有idata()+i==&operator[](i),并且[strings.access]/2中指定operator[]在没有任何条件的情况下返回对CharT()(又名空字符)的引用,对于operator[](size())

这种奇怪的措辞也已经在2018年通过编辑更改得到了替换,请参见https://github.com/cplusplus/draft/pull/1879


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接