c++ - 为什么没有通过 ""比较检查空字符串的优化?

标签 c++ gcc clang c++14

这个 google-benchmark 代码在 Quick Bench 上检查过, 显示 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因为它清楚地表明 myVariablestd::string没有不必要的困惑。为什么我们不能像所有其他情况一样对其进行优化?

最佳答案

对于空性检查,如果你真的喜欢文字语法,你可以通过 using namespace std::string_literals; 帮助你的编译器,并替换 """"s .在那种情况下 compareWithLiteral , compareWithRvaluecheckForEmpty基本相同,因为 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::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大小不一样。

关于c++ - 为什么没有通过 ""比较检查空字符串的优化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62081977/

相关文章:

c++ - 使用 CMake 和 clang 在 Windows 上构建一个简单的 C++ 项目

c++ - dynamic_cast 一个非常量引用到一个常量引用。 cppreference.com 的解释似乎很奇怪

c++ - 使用operator[]时如何区分读/写操作

c++ - 为什么这个程序没有优化掉?

python - 从源构建 TensorFlow 时,生成 `gen_io_ops.py` 文件的 bazel 规则在哪里?

gcc - GCC功能后缀“isra”是什么意思?

c++ - LibClang clang_getArgType() 返回错误的类型

gcc - 将c++目标文件链接到c目标文件

c位运算bug

c - 我需要在 LLVM 中实现什么才能使 Clang 为自定义架构生成 IR?