我应该将 std::string 与 "string" 还是 "string" 进行比较?
Should I compare a std::string to "string" or "string"s?
考虑这个代码片段:
bool foo(const std::string& s) {
return s == "hello"; // comparing against a const char* literal
}
bool bar(const std::string& s) {
return s == "hello"s; // comparing against a std::string literal
}
在 first sight,看起来与 const char*
相比需要更少的汇编指令1,因为使用字符串文字会导致 in- std::string
.
的位置构造
(编辑:正如答案中所指出的,我忘记了实际上 s.compare(const char*)
将在 foo()
中被调用的事实,所以当然在这种情况下没有就地施工。因此删除下面的一些行。)
但是,看着 operator==(const char*, const std::string&)
reference:
All comparisons are done via the compare()
member function.
根据我的理解,这意味着我们无论如何都需要构造一个 std::string
来执行比较,所以我怀疑最终开销会相同(尽管隐藏在对operator==
).
- 我应该选择哪个比较?
- 一个版本是否比另一个版本有优势(可能在特定情况下)?
1 我知道更少的汇编指令并不一定意味着更快的代码,但我不想在这里进行微基准测试。
不,compare()
不需要为 const char*
操作数构造 std::string
。
您正在使用 overload #4 here。
与字符串文字的比较是您要查找的 "free" 版本。在这里实例化一个 std::string
是完全没有必要的。
From my understanding, this means that we will need to construct a std::string
anyway in order to perform the comparison, so I suspect the overhead will be the same in the end (although hidden by the call to operator==
).
这就是推理错误的地方。 std::compare
不需要将其操作数分配为 C-style null-terminated 字符串来运行。根据其中一个重载:
int compare( const CharT* s ) const; // (4)
4) Compares this string to the null-terminated character sequence beginning at the character pointed to by s
with length Traits::length(s)
.
虽然是否分配是一个实现细节,但顺序比较似乎并不合理。
都没有。
要聪明就比较"string"sv
, which returns a std::string_view
.
虽然与 "string"
这样的文字进行比较不会产生任何 allocation-overhead,但它被视为以空字符结尾的字符串,并具有所有伴随的缺点:不能容忍嵌入的空值,用户必须注意空终止符。
"string"s
进行分配, or 除外。此外,运算符会传递文字的长度,无需计数,并且它允许嵌入空值。
最后使用 "string"sv
结合了其他两种方法的优点,避免了各自的缺点。此外,std::string_view
比 std::string
简单得多,特别是如果后者像所有现代的一样使用 SSO。
至少从 C++14(通常允许省略分配)开始,编译器在理论上可以将所有选项优化到最后一个,只要有足够的信息(通常可用于该示例)和努力,在 as-if rule.不过我们还没有。
考虑这个代码片段:
bool foo(const std::string& s) {
return s == "hello"; // comparing against a const char* literal
}
bool bar(const std::string& s) {
return s == "hello"s; // comparing against a std::string literal
}
在 first sight,看起来与 const char*
相比需要更少的汇编指令1,因为使用字符串文字会导致 in- std::string
.
(编辑:正如答案中所指出的,我忘记了实际上 s.compare(const char*)
将在 foo()
中被调用的事实,所以当然在这种情况下没有就地施工。因此删除下面的一些行。)
但是,看着 operator==(const char*, const std::string&)
reference:
All comparisons are done via the
compare()
member function.
根据我的理解,这意味着我们无论如何都需要构造一个 std::string
来执行比较,所以我怀疑最终开销会相同(尽管隐藏在对operator==
).
- 我应该选择哪个比较?
- 一个版本是否比另一个版本有优势(可能在特定情况下)?
1 我知道更少的汇编指令并不一定意味着更快的代码,但我不想在这里进行微基准测试。
不,compare()
不需要为 const char*
操作数构造 std::string
。
您正在使用 overload #4 here。
与字符串文字的比较是您要查找的 "free" 版本。在这里实例化一个 std::string
是完全没有必要的。
From my understanding, this means that we will need to construct a
std::string
anyway in order to perform the comparison, so I suspect the overhead will be the same in the end (although hidden by the call tooperator==
).
这就是推理错误的地方。 std::compare
不需要将其操作数分配为 C-style null-terminated 字符串来运行。根据其中一个重载:
int compare( const CharT* s ) const; // (4)
4) Compares this string to the null-terminated character sequence beginning at the character pointed to by
s
with lengthTraits::length(s)
.
虽然是否分配是一个实现细节,但顺序比较似乎并不合理。
都没有。
要聪明就比较"string"sv
, which returns a std::string_view
.
虽然与 "string"
这样的文字进行比较不会产生任何 allocation-overhead,但它被视为以空字符结尾的字符串,并具有所有伴随的缺点:不能容忍嵌入的空值,用户必须注意空终止符。
"string"s
进行分配,
最后使用 "string"sv
结合了其他两种方法的优点,避免了各自的缺点。此外,std::string_view
比 std::string
简单得多,特别是如果后者像所有现代的一样使用 SSO。
至少从 C++14(通常允许省略分配)开始,编译器在理论上可以将所有选项优化到最后一个,只要有足够的信息(通常可用于该示例)和努力,在 as-if rule.不过我们还没有。