std::string()和std::string("")一样吗?

13
假设我有一个返回 std::string 的函数。由于某些情况,该字符串没有被填充任何内容。

那么返回 std::string() 是否与 std::string("") 完全等效?例如,c_str()data() 会给你相同的字符序列吗?也许 std::string("") 会激活短字符串优化,但 std::string() 只有在添加了一些字符后才执行此操作。

有没有人知道当前标准(C++11)是否有任何明确的规定?


+1,以http://en.cppreference.com/w/cpp/string/basic_string/basic_string作为标准的代理,它并不清楚。 - Bathsheba
1
@SlodgeMonster:通过更改您的“解决方案”指定,您可以帮助其他人。当前选择的不正确。 - Cheers and hth. - Alf
1
被接受的答案有什么不正确的地方吗?我也点赞了它。从您的个人资料中可以看出,您可能能够提供一个可信的答案。 - Bathsheba
@Bathsheba:有三个人(包括我)在quantdev当前选择的答案下面留了评论,提供了三种不同的解释。 - Cheers and hth. - Alf
4个回答

6

std::string上,没有任何成员函数可以区分std::string()std::string("")

我建议请一位哲学家或逻辑学家验证这是否符合任何等式的定义。

至于标准本身,它声明std::string()将保留未指定的容量,而std::string("")将定义至少为零的容量。因此,对象的内部状态可能不同。

在我的特定STL实现(MSVC2012)中,std::string()调用一个名为_Tidy的函数,而std::string("")调用_Tidyassign。(基类初始化是相同的)。assign是一个标准的std::string函数。

所以它们可能是不同的吗?是的。 你能告诉它们是否不同吗?不能


1
没有成员函数可以区分它们 - 除了 capacity(),正如你自己所说的那样。 - Mike Seymour
1
但是在std::string()情况下,capacity()不会告诉您任何有意义的信息(即仍然无法与显式设置的容量区分开来),但同意这在我的答案中并不特别清楚。 - Bathsheba
1
实际上,我并没有说它有用。这只是与你的声明相矛盾:“在std::string上肯定没有成员函数可以让你区分它们。” - Mike Seymour
2
@Bathsheba std::string::size_type 是无符号的,因此它不能返回 -1。而“至少为零”与“未指定”是相同的意思。 - Oktalist
2
“-1” “将不指定容量,但std::string(“”)将定义至少为零的容量。因此,对象的内部状态可能会有所不同。”是愚蠢的。容量始终为零或更大。 - Cheers and hth. - Alf
显示剩余2条评论

4
如果我们查看C++标准中每个构造函数的影响,第21.4.2节[string.cons]如下所示:
对于explicit basic_string(const Allocator& a = Allocator())
  • data():一个非空指针,可复制,并且可以将0添加到其中。
  • size() :0
  • capacity() :一个未指定的值
对于basic_string(const charT* s, const Allocator& a = Allocator())
  • data():指向分配的副本的第一个元素的数组的第一个元素
  • size()traits::length(s)
  • capacity() :至少与size()一样大的值
因此,严格来说,这两种构造函数并不相同:特别是,构造的std :: string对象的容量可能会有所不同。
实际上,这种可能的差异不太可能对您的代码产生任何可观察的影响。

4
按照相同的论点,“std::string{}”和“std::string{ }”并不相同。 - Oktalist
@Oktalist 你是不是想要重复两次使用 std::string{} - Uyghur Lives Matter
@cpburnz 是的,因为容量可能不同。 - Oktalist
3
非相同的结论是无意义的。保证的行为是相同的。对于非保证的行为(例如容量),自由度也是相同的。 - Cheers and hth. - Alf
1
capacity():未指定的值capacity():至少与size()一样大的值有什么区别,其中size() = 0 - Mohit Jain

3
是的,它们都是相同的。std::string的默认构造函数会准备一个空字符串,与""相同。

explicit basic_string( const Allocator& alloc = Allocator() );
默认构造函数。构造空字符串(大小为零且容量未指定)。

basic_string( const CharT* s, const Allocator& alloc = Allocator() );
用由s指向的以空字符结尾的字符数组初始化字符串的内容。字符串的长度由第一个空字符确定。如果s没有指向至少有Traits::length(s)+1个CharT元素的数组,则行为未定义。


2
但我没有看到第二个构造函数中指定容量的地方,因此构造出来的对象可能是不同的。 - P45 Imminent
1
它是从 Traits::length 用于 std::string 或 chartrait 中取得的,它类似于 strlenstrlen("") 的结果为0。 - Mohit Jain
2
你的报价明确表示容量未指定,因此它们不一定完全相同。 - Mike Seymour
2
@MikeSeymour 在这两种情况下,容量都未指定。或者,“不小于零的某个无符号整数”是否意味着与“未指定的无符号整数”有所不同? - Oktalist
1
@MikeSeymour:capacity >= 0 表示容量在范围 0...SIZE_MAX 内。未指定的容量意味着容量在范围 0...SIZE_MAX 内。两者没有区别。 - Cheers and hth. - Alf
显示剩余19条评论

2
唯一的区别在于,std::string() 在编译时就知道会生成一个长度为零的字符串,而std::string("")必须在运行时使用strlen或类似的方法来确定它将构造的字符串的长度。因此,默认构造函数应该更快。

+1并不是错误的答案。然而,关于效率的猜测可能是错误的,因为可以通过一次获取和一次零检查来确定C字符串的空值。这就像是无法测量的。 - Cheers and hth. - Alf
2
我不同意""的长度必须在运行时确定。优化编译器可以内联构造函数,并将长度检查替换为零常量。 - reima

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