请考虑以下代码段:
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 ,因为使用字符串文字将导致{的就地构造{1}}。
但是,看着 operator==(const char*, const std::string&)
reference:
所有比较都是通过
std::string
成员函数完成的。
根据我的理解,这意味着无论如何我们都需要构造一个 compare()
才能进行比较,因此我怀疑最终的开销是一样的(尽管被std::string
的调用隐藏了。)
(编辑:如答案中所指出,我忘记了实际上将在operator==
中调用s.compare(const char*)
的事实,因此当然就地构建不需要在这种情况下放置)
1 我知道更少的汇编指令并不一定意味着更快的代码,但是我不想在这里进行微基准测试。
答案 0 :(得分:65)
如果您想变得聪明一点,可以将其与"string"sv
进行比较,后者将返回std::string_view
。
与"string"
之类的文字进行比较时,不会导致任何分配开销,但会将其视为以null结尾的字符串,同时具有所有伴随的缺点:不能接受嵌入的null,用户必须注意null终止符
"string"s
进行分配,但禁止small-string-optimisation或allocation elision。另外,运算符可以传递文字的长度,而无需计数,并且允许嵌入空值。
最后使用"string"sv
结合了其他两种方法的优点,避免了它们各自的缺点。另外,std::string_view
比std::string
更简单,尤其是当后者像所有现代人一样使用SSO时。
至少从C ++ 14(通常允许省略分配)开始,在as-if rule下,只要有足够的信息(通常可用于示例)和努力,编译器理论上就可以优化最后一个的所有选项。 。我们还没到那儿。
答案 1 :(得分:13)
否,compare()
不需要为std::string
个操作数构造const char*
。
您正在使用overload #4 here。
与字符串文字的比较是您要查找的“免费”版本。完全不需要在此处实例化std::string
。
答案 2 :(得分:9)
据我了解,这意味着无论如何我们都需要构造一个
std::string
才能进行比较,因此我怀疑最终的开销是一样的(尽管对{{ 1}})。
这就是推理出错的地方。 std::compare
不需要将其操作数分配为C样式的以null终止的字符串即可起作用。根据重载之一:
operator==
4)将此字符串与以
int compare( const CharT* s ) const; // (4)
指向的字符(长度为s
所指向的字符开始的以空终止的字符序列进行比较。
尽管是否分配是实现细节,但是序列比较这样做似乎并不合理。