在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
。为什么我们不能像其他所有情况一样对它进行优化?
对于空度检查,如果您确实喜欢字面语法,则可以通过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具有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
大小不同的情况下。