【发布时间】:2020-03-28 05:27:17
【问题描述】:
我最近发现了类似于以下几行的内容:
#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? 的重复,因为我完全了解您将如何正确编写函数!
我开始怀疑编译器会如何处理这个 sn-p。我的第一个直觉是这基本上会被编译成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
所以我的核心问题是:我错过了什么不允许编译器在第一个 sn-p 上进行相同的优化?
1使用".foo"s 这甚至无法编译,因为编译器不想将std::string 转换为bool ;-)
编辑
以下代码也“正确”优化为return true;:
#include <string>
bool test_extension(const std::string& ext) {
return ".foo" || ext == ".bar";
}
【问题讨论】:
-
嗯,
string::compare(const char*)是否有一些编译器无法消除的副作用(operator==(string, string)没有)?似乎不太可能,但编译器确实已经确定结果始终为真(也有mov eax, 1ret),即使对于第一个 sn-p。 -
可能是因为
operator==(string const&, string const&)是noexcept而operator==(string const&, char const*)不是?我现在没有时间进一步挖掘。 -
@MaxLanghof 将顺序更改为
foo || ext == ".bar"时,调用已被优化掉(见编辑)。这是否与您的理论相矛盾? -
@AlexV 我不确定这应该是什么意思。表达式
a || b的短路意味着“仅当表达式a是false时才评估表达式b”。它与运行时或编译时正交。true || foo()可以优化为true,即使foo()有副作用,因为(无论是否优化)右侧永远不会被评估。但是foo() || true不能优化为true,除非编译器可以证明调用foo()没有可观察到的副作用。 -
当我获取您提供的编译器资源管理器链接并检查“编译为二进制并反汇编输出”选项时,它会突然编译为
xor eax,eax,即使没有该选项它也会调用字符串比较函数。我不知道该怎么做。
标签: c++ string c++14 compiler-optimization