为什么没有通过“”比较检查空字符串的优化?

Ada*_*adi 5 c++ gcc clang c++14

Quick Bench上检查的这个 google-benchmark 代码表明,它的string::empty()运行速度比与空字符串文字相比要快得多。但是,创建一个名称字符串""实际上会使编译器优化检查:

bool compareWithNamedConst(const std::string& target) {
    const std::string emptyString = "";
    return emptyString == target;
}

bool compareWithLiteral(const std::string& target) {
    return "" == target;
}

bool compareWithRvalue(const std::string& target) {
    return std::string{""} == target;
}

bool checkForEmpty(const std::string& target) {
    return target.empty();
}
Run Code Online (Sandbox Code Playgroud)

每个调用的性能如下所示:

正如您所看到的,与""所有其他选项相比,比较速度非常慢。我想知道为什么会这样?它必须以某种方式与未应用 SSO 相关const char*,作为测试:

bool compareWithLiteral(const std::string& target) {
    return "test with a longer string not optimized" == target;
}

bool compareWithRvalue(const std::string& target) {
    return std::string{"test with a longer string not optimized"} == target;
}
Run Code Online (Sandbox Code Playgroud)

结果与文字相比实际上更快:

我发现,检查字符串空虚,最简单的语法来读是"" == myVariable因为它清楚地表明,myVariable是一个std::string没有unneccesary混乱。为什么我们不能像所有其他情况一样对其进行优化?

Gio*_*ani 1

对于空性检查,如果您真的喜欢文字语法,您可以通过using namespace std::string_literals;, 并替换""为 来帮助您的编译器""s。在这种情况下compareWithLiteralcompareWithRvaluecheckForEmpty本质上是相同的,因为operator==Betweenconst std::string&通常会在内容之前检查大小,而 的大小""s是微不足道的。

bool compareWithLiteral(const std::string& target) {
    using namespace std::string_literals;
    return ""s == target;
}
Run Code Online (Sandbox Code Playgroud)

对于不属于 SSO 的字符串,您应该尝试使用std::string_view和 its operator""sv,即使不幸的是仅从 C++17 开始可用。升压有boost::string_view. 没有为编译时创建提供用户字符串文字(这是必需的,因为测试字符串长度将在二进制文件中硬编码),但您可以轻松定义一个:

#include <boost/utility/string_view.hpp>

constexpr auto operator""_sv(const char* str, std::size_t len) noexcept {
    return boost::basic_string_view<char>{str, len};
}

bool compareWithLiteral(const std::string& target) {
    return "test with a longer string not optimized"_sv == target;
}
Run Code Online (Sandbox Code Playgroud)

该版本的运行速度比您的版本快得多compareWithLiteral,至少在target大小不同时是这样。

  • 虽然这是真的(恕我直言,这是个好建议),但这根本没有回答OP的问题,这不是*如何*有效地执行检查,而是*为什么*与C风格字符串的比较没有得到优化。 (4认同)