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

问题描述 投票:2回答:1

Quick Bench上选中的这个Google基准代码,表明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();
}

此处显示每个呼叫的性能:

如您所见,与所有其他选项相比,与""进行比较非常慢。我不知道为什么会这样吗?测试它一定与在const char*上未应用SSO有关:

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;
}

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

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

c++ gcc clang c++14
1个回答
0
投票

对于空度检查,如果您确实喜欢字面语法,则可以通过using namespace std::string_literals;帮助编译器,并用""替换""s。在那种情况下,compareWithLiteralcompareWithRvaluecheckForEmpty基本上是相同的,因为operator==之间的const std::string&通常检查内容之前的大小,而""s的大小是微不足道的。

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

对于不落入SSO的字符串,您应该尝试使用std::string_view及其operator""sv,即使不幸的是,仅从C ++ 17开始才可用。 Boost具有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;
}

此版本的运行速度比compareWithLiteral版本快得多,至少在target大小不同的情况下。

© www.soinside.com 2019 - 2024. All rights reserved.