这个 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
因为它清楚地表明 myVariable
是 std::string
没有不必要的困惑。为什么我们不能像所有其他情况一样对其进行优化?
最佳答案
对于空性检查,如果你真的喜欢文字语法,你可以通过 using namespace std::string_literals;
帮助你的编译器,并替换 ""
与 ""s
.在那种情况下 compareWithLiteral
, compareWithRvalue
和 checkForEmpty
基本相同,因为 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/