我最近发现了类似以下的代码:
#include <string>
// test if the extension is either .bar or .foo
bool test_extension(const std::string& ext) {
return ext == ".bar" || ".foo";
// it obviously should be
// return ext == ".bar" || ext == ".foo";
}
这个函数显然没有按照注释所建议的那样执行。但这不是重点。请注意,这不是Can you use 2 or more OR conditions in an if statement?的重复,因为我完全知道如何正确编写函数!
我开始想知道编译器如何处理这个代码片段。我的第一反应是,这基本上会被编译为return true;
。将示例插入到godbolt中,显示GCC 9.2和clang 9都不使用优化-O2
进行此优化。
但是,将代码更改为1
#include <string>
using namespace std::string_literals;
bool test_extension(const std::string& ext) {
return ext == ".bar"s || ".foo";
}
似乎做到了目的,因为装配现在本质上是:
mov eax, 1
ret
我的核心问题是:我是否忽略了什么,以致于编译器无法对第一个代码片段进行相同的优化?
1使用".foo"s
将无法编译,因为编译器不希望将std::string
转换为bool
;-)
编辑
以下代码片段也被“正确地”优化为return true;
:
#include <string>
bool test_extension(const std::string& ext) {
return ".foo" || ext == ".bar";
}
operator==(string const&, string const&)
是noexcept
的,而operator==(string const&, char const*)
不是?我现在没有时间深入挖掘。 - AProgrammera || b
的短路运算,意味着“只有在表达式a
为false
时才计算表达式b
”。这与运行时或编译时无关。即使foo()
具有副作用,true || foo()
也可以被优化为true
,因为(无论是否被优化)右侧都不会被计算。但是,除非编译器能够证明调用foo()
没有可观察的副作用,否则foo() || true
不能被优化为true
。 - Max Langhofxor eax,eax
,即使没有该选项,它也会调用字符串比较函数。我不知道该怎么解释这个现象。 - Daniel H