Ich habe kürzlich etwas gefunden, das den folgenden Zeilen ähnelt:
#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";
}
Die Funktion macht offensichtlich nicht das, was der Kommentar vorschlägt. Aber darum geht es hier nicht. Bitte beachten Sie, dass dies kein Duplikat von Können Sie 2 oder mehr ODER-Bedingungen in einer if-Anweisung verwenden? da ich mir voll bewusst bin, wie du die Funktion richtig schreiben würdest!
Ich begann mich zu fragen, wie ein Compiler dieses Snippet behandeln könnte. Meine erste Intuition wäre gewesen, dass dies im return true;
Grunde genommen kompiliert würde . Das Einstecken des Beispiels in Godbolt zeigte, dass weder GCC 9.2 noch Clang 9 diese Optimierung mit Optimierung durchführen -O2
.
Ändern des Codes in 1
#include <string>
using namespace std::string_literals;
bool test_extension(const std::string& ext) {
return ext == ".bar"s || ".foo";
}
scheint den Trick zu tun, da die Versammlung jetzt im Wesentlichen ist:
mov eax, 1
ret
Meine Kernfrage lautet also: Gibt es etwas, das ich verpasst habe und das es einem Compiler nicht ermöglicht, beim ersten Snippet dieselbe Optimierung vorzunehmen?
1 Mit ".foo"s
dieser würde nicht einmal kompilieren, da der Compiler nicht konvertieren will eine std::string
zu bool
;-)
Bearbeiten
Der folgende Code wird ebenfalls "richtig" optimiert für return true;
:
#include <string>
bool test_extension(const std::string& ext) {
return ".foo" || ext == ".bar";
}
operator==(string const&, string const&)
ist, noexcept
während das operator==(string const&, char const*)
nicht ist? Ich habe jetzt keine Zeit, das weiter zu graben.
foo || ext == ".bar"
wird der Anruf weg optimiert (siehe Bearbeiten). Widerspricht das Ihrer Theorie?
a || b
bedeutet "Ausdruck b
nur bewerten, wenn Ausdruck a
ist false
". Es ist orthogonal zur Laufzeit oder zur Kompilierungszeit. true || foo()
kann optimiert werden true
, auch wenn foo()
Nebenwirkungen auftreten, da (egal ob optimiert oder nicht) die rechte Seite niemals bewertet wird. Aber foo() || true
kann nicht optimiert werden , true
es sei denn der Compiler nachweisen kann , dass Berufung foo()
keine feststellbaren Nebenwirkungen hat.
xor eax,eax
obwohl er ohne diese Option die Funktion zum Vergleichen von Zeichenfolgen aufruft. Ich habe keine Ahnung, was ich davon halten soll.
string::compare(const char*)
es einige Nebenwirkungen, die der Compiler nicht beseitigen wird (dieoperator==(string, string)
es nicht gibt)? Scheint unwahrscheinlich, aber der Compiler hat bereits festgestellt, dass das Ergebnismov eax, 1
ret
auch für das erste Snippet immer wahr ist (auch hat ).