私は最近、次のようなものを見つけました。
#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";
}
関数は明らかにコメントが示唆することを行いません。しかし、それはここでのポイントではありません。これはifステートメントで2つ以上のOR条件を使用できますか?あなたが関数を適切に書く方法を私は完全に知っているので!
コンパイラがこのスニペットをどのように処理するのか疑問に思い始めました。私の最初の直感は、これが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
では、コンパイラはa 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*)
はないのですか?これをさらに掘り下げる時間はありません。
foo || ext == ".bar"
に変更すると、呼び出しは最適化されます(編集を参照)。それはあなたの理論と矛盾していますか?
a || b
「b
式a
が次の場合のみ式を評価する」ことを意味しfalse
ます。実行時またはコンパイル時と直交しています。(最適化されているかどうかにかかわらず)右側が評価されないため、副作用がある場合でも、true || foo()
をに最適化できます。ただし、コンパイラーが呼び出しに観察可能な副作用がないことを証明できない限り、最適化できません。true
foo()
foo() || true
true
foo()
xor eax,eax
すると、文字列比較関数を呼び出すオプションがないにもかかわらず、突然コンパイルされます。何を作ればいいのか分かりません。
string::compare(const char*)
コンパイラが排除operator==(string, string)
しない(それがない)副作用がありますか?可能性は低いと思われますが、コンパイラーはmov eax, 1
ret
、最初のスニペットであっても、結果が常に真(である)であると既に判断していました。