我应该将std :: string与“ string”或“ string” s比较吗?

and*_*eee 44 c++ string-comparison string-literals c++14 c++17

考虑以下代码片段:

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
}
Run Code Online (Sandbox Code Playgroud)

乍一看,它看起来像比对并const char*需要更少的组装说明1,作为使用字符串字面量会导致就地建设std::string

编辑:正如答案中指出的那样,我忘记了有效地s.compare(const char*)将被调用的事实foo(),因此在这种情况下当然不会进行就地构建。因此,请在下面删除一些行。

但是,请operator==(const char*, const std::string&)参阅参考资料:

所有比较都是通过compare()成员函数完成的。

根据我的理解,这意味着我们将需要构造一个结构std::string来执行比较,因此我怀疑最终的开销将是相同的(尽管对的调用已将其隐藏了operator==)。

  • 我应该选择哪个比较?
  • 一个版本是否比另一个版本具有优势(可能在特定情况下)?

1我知道更少的汇编指令并不一定意味着更快的代码,但是我不想在这里进行微基准测试。

Ded*_*tor 66

都不行

如果您想变得聪明一点,请与进行比较"string"sv,以返回std::string_view


虽然与类似的文字进行比较"string"不会导致任何分配开销,但会将其视为以null结尾的字符串,同时具有所有伴随的缺点:不能容忍嵌入的null,用户必须注意null终止符。

"string"s进行分配,除非进行小字符串优化分配省略。而且,运算符可以传递文字的长度,无需计数,并且允许嵌入空值。

最后使用"string"sv结合了其他两种方法的优点,避免了它们各自的缺点。而且,a std::string_view比a兽简单得多std::string,尤其是当a 像所有现代动物一样使用SSO时。


在因为C语言至少++ 14(一般允许eliding分配),编译器在理论上可以优化给予足够的信息,所有的选择到最后一个,(一般适用于例如)和努力,在AS-如果规则。我们还没到那儿。

  • @LightnessRacesinOrbit没有使用`operator“” sv`创建string_view的`strlen()`。 (10认同)
  • 实际上,使用`-O3`,gcc甚至可以[内联对`compare`的调用](https://godbolt.org/z/pQ2r7m),这在常规字符串文字中不会发生。 (7认同)
  • 抱歉,与简单的字符串文字相比,这样做有什么好处?不要误会我的意思,我喜欢字符串视图,并在适当的时候明智地使用它们,但是我在这里没有看到它。 (5认同)
  • 使用string_view [looks](https://godbolt.org/z/jVUzSd)可以在`gcc9.1 -Ofast`上最快,因为它内联了比较对象。使用`-Os'时,string_view和字符串文字版本都调用`memcmp`。 (4认同)
  • @xception是的。不幸的是,该标准以令人难以置信的理由谈论了诸如此类的令人难以置信的较新的重载(而不是仅仅列出重载及其简单参数的老式方法)。但您要的是[这里7-9](https://en.cppreference.com/w/cpp/string/basic_string/compare)。 (3认同)

Lig*_*ica 13

不,compare()不需要std::stringconst char*操作数构造a 。

您在这里使用#4重载

与字符串文字的比较是您要查找的“免费”版本。在std::string这里实例化a 完全没有必要。

  • @Someprogrammerdude在这个抽象级别上是免费的,是的。从理论上讲,该实现可以设计为避免与云进行比较,从而导致数毫秒的延迟,并有可能登录到Facebook-但让我们成为现实;) (5认同)

E_n*_*ate 9

根据我的理解,这意味着我们将需要构造一个结构std::string来执行比较,因此我怀疑最终的开销将是相同的(尽管对的调用已将其隐藏了operator==)。

这就是推理出错的地方。std::compare不需要将其操作数分配为C样式的以null终止的字符串即可起作用。根据重载之一:

int compare( const CharT* s ) const; // (4)
Run Code Online (Sandbox Code Playgroud)

4)在由指向的字符比较此字符串的空终止字符序列开始s与长度Traits::length(s)

尽管是否分配是实现细节,但是序列比较这样做似乎并不合理。