Ist der Operator ?: In C ++ schneller als if () ... else-Anweisungen? Gibt es Unterschiede zwischen ihnen im kompilierten Code?
if
Anweisungen zulässig sind.
Ist der Operator ?: In C ++ schneller als if () ... else-Anweisungen? Gibt es Unterschiede zwischen ihnen im kompilierten Code?
if
Anweisungen zulässig sind.
Antworten:
Hängt von Ihrem Compiler ab, aber bei jedem modernen Compiler gibt es im Allgemeinen keinen Unterschied. Darüber sollten Sie sich keine Sorgen machen. Konzentrieren Sie sich auf die Wartbarkeit Ihres Codes.
Es ist nicht schneller. Es gibt einen Unterschied, wenn Sie eine konstante Variable abhängig von einem Ausdruck initialisieren können:
const int x = (a<b) ? b : a;
Mit dem kann man nicht dasselbe machen if-else
.
const
Variablen nicht möglich ist.
max
? const int x = max(a,b);
funktioniert gut.
max ? const int x = max(a,b);
und dachte whoa! Was zum Teufel ist das! dann las ich es noch einmal und bemerkte, dass das Fragezeichen kein Monospace war! Angesichts des Themas denke ich, dass ich berechtigt war, das zu denken? war Teil des Befehls! :)
Ich habe gesehen, wie GCC den bedingten Operator in cmov
Anweisungen (bedingte Verschiebung) umwandelte, während if
Anweisungen in Zweige umgewandelt wurden, was in unserem Fall bedeutete, dass der Code bei Verwendung des bedingten Operators schneller war. Aber das war vor ein paar Jahren und höchstwahrscheinlich würden beide heute mit demselben Code kompiliert werden.
Es gibt keine Garantie dafür, dass sie mit demselben Code kompiliert werden. Wenn Sie die Leistung benötigen, messen Sie wie immer . Und wenn Sie gemessen und herausgefunden haben, dass 1. Ihr Code zu langsam ist und 2. dieser bestimmte Codeabschnitt der Schuldige ist, studieren Sie den vom Compiler generierten Assembler-Code und überprüfen Sie selbst, was passiert.
Vertrauen Sie nicht goldenen Regeln wie "Der Compiler generiert immer effizienteren Code, wenn ich den bedingten Operator verwende".
Only one of the second and third expressions is evaluated. Every value computation and side effect associated with the first expression is sequenced before every value computation and side effect associated with the second or third expression.
was den Compiler anscheinend daran hindert, cmove
Anweisungen zu generieren .
Sie sind die gleichen, jedoch kann der ternäre Operator an Orten verwendet werden, an denen es schwierig ist, ein if / else zu verwenden:
printf("Total: %d item%s", cnt, cnt != 1 ? "s" : "");
Wenn Sie diese Anweisung mit einem if / else ausführen, wird ein ganz anderer kompilierter Code generiert.
Update nach 8 Jahren ...
Eigentlich denke ich, das wäre besser:
printf(cnt == 1 ? "Total: %d item" : "Total: %d items", cnt);
(Eigentlich bin ich mir ziemlich sicher, dass Sie das "% d" in der ersten Zeichenfolge durch "eins" ersetzen können.)
printf("Total: %d item%s", cnt, "s" + (cnt==1));
lpStrFilter
Mitglied von OPENFILENAME-Strukturen )
%s
bis zu, jedoch ohne die \0
aus der Quellzeichenfolge .
printf("Total: %d item%s", cnt, "s" + (cnt==1));
?
(cnt==1)
ist wahr oder falsch, was in 0 oder 1 konvertiert wird. "S" ist ein Zeiger auf eine nicht terminierte Zeichenfolge. Beim Hinzufügen eines Zeichens wird ein Zeichen (das s) übersprungen. Dies druckt also entweder "s" oder "".
Nur um ein bisschen Linkshänder zu sein ...
x ? y : x = value
weist y einen Wert zu, wenn x nicht 0 ist (falsch).
Unabhängig vom kompilierten Code sind sie semantisch anders. <cond>?<true expr>:<false expr>
ist ein Ausdruck und if..else..
eine Aussage.
Obwohl die Syntax des bedingten Ausdrucks unangenehm erscheint, ist sie eine gute Sache. Sie müssen a angeben <false expr>
und die beiden Ausdrücke werden typgeprüft.
Das Äquivalent zu einer if..else..
ausdrucksbasierten, funktionalen Sprache wie Lisp ist Haskell ? :
in C ++ anstelle von if..else..
Anweisung.
Ich würde erwarten, dass es auf den meisten Compilern und Zielplattformen Fälle gibt, in denen "wenn" schneller ist und Fälle, in denen ?: Schneller ist. Es wird auch Fälle geben, in denen eine Form mehr oder weniger kompakt ist als die andere. Welche Fälle die eine oder andere Form bevorzugen, hängt von Compilern und Plattformen ab. Wenn Sie leistungskritischen Code auf ein eingebettetes Mikro schreiben, überprüfen Sie, was der Compiler jeweils generiert, und finden Sie heraus, welcher Code besser ist. Auf einem "Mainstream" -PC besteht die einzige Möglichkeit, aufgrund von Caching-Problemen zu erkennen, welche besser ist, darin, beide Formen in einer Weise zu vergleichen, die der tatsächlichen Anwendung ähnelt.
In CA ist der ternäre Operator "?:" Verfügbar, um bedingte Ausdrücke des Formulars zu erstellen
exp1 ? exp2:exp3
Dabei sind exp1, exp2 und exp3 Ausdrücke
zum Beispiel
a=20;
b=25;
x=(a>b)?a:b;
in the above example x value will be assigned to b;
Dies kann mit der if..else- Anweisung wie folgt geschrieben werden
if (a>b)
x=a;
else
x=b;
** Daher gibt es keinen Unterschied zwischen diesen beiden. Dies ist für den Programmierer leicht zu schreiben, aber für den Compiler sind beide gleich. *
Beim Umkehren eines Codes (an den ich mich vor einigen Jahren nicht mehr erinnere) habe ich einen einzeiligen Unterschied zwischen dem Maschinencode von :? und wenn-sonst.
Don't remember much but it is clear that implementation of both is different.
Aber ich rate Ihnen, keinen von ihnen zu wählen, weil er effizient ist, sondern je nach Lesbarkeit des Codes oder Ihrer Bequemlichkeit. Viel Spaß beim Codieren
Der ternäre Operator gibt immer einen Wert zurück. In Situationen, in denen Sie einen Ausgabewert aus dem Ergebnis wünschen und es nur zwei Bedingungen gibt, ist es immer besser, den ternären Operator zu verwenden. Verwenden Sie if-else, wenn eine der oben genannten Bedingungen nicht erfüllt ist.
Ich denke, dass es Situationen gibt, in denen das Inline-If aufgrund des Umfangs, in dem es funktioniert, "schnelleren" Code liefern kann. Das Erstellen und Zerstören von Objekten kann kostspielig sein. Betrachten Sie daher das folgende Szenario:
class A{
public:
A() : value(0) {
cout << "Default ctor" << endl;
}
A(int myInt) : value(myInt)
{
cout << "Overloaded ctor" << endl;
}
A& operator=(const A& other){
cout << "= operator" << endl;
value = other.value;
}
~A(){
cout << "destroyed" << std::endl;
}
int value;
};
int main()
{
{
A a;
if(true){
a = A(5);
}else{
a = A(10);
}
}
cout << "Next test" << endl;
{
A b = true? A(5) : A(10);
}
return 0;
}
Mit diesem Code lautet die Ausgabe:
Default ctor
Overloaded ctor
= operator
destroyed
destroyed
Next test
Overloaded ctor
destroyed
Indem wir das if einfügen, sparen wir eine Reihe von Operationen, die erforderlich sind, um a
im gleichen Umfang wie am Leben zu bleiben b
. Während es sehr wahrscheinlich ist, dass die Geschwindigkeit der Zustandsbewertung in beiden Szenarien ziemlich gleich ist, zwingt eine Änderung des Bereichs Sie dazu, andere Faktoren zu berücksichtigen, die Sie durch Inline-If vermeiden können.
A a(true ? 5 : 10);
Jetzt kann ich Ihnen dabei nicht helfen. Vielleicht kann ich Ihnen bei einer sekundären Frage helfen. Möchte ich sie verwenden? Wenn Sie nur die Geschwindigkeit wissen möchten, ignorieren Sie einfach meinen Kommentar.
Ich kann nur sagen, bitte seien Sie sehr schlau, wann Sie das Ternär verwenden sollen. : Operator. Es kann sowohl ein Segen als auch ein Fluch für die Lesbarkeit sein.
Fragen Sie sich, ob Sie dies leichter lesen können, bevor Sie es verwenden
int x = x == 1 ? x = 1 : x = 1;
if (x == 1)
{
x = 1
}
else
{
x = 2
}
if (x == 1)
x = 1
else
x = 1
Ja, es sieht dumm aus, den Code zu 100% falsch zu machen. Aber dieser kleine Trick hat mir geholfen, meine Lesbarkeit von Code zu analysieren. Es ist die Lesbarkeit des Operators, den Sie in diesem Beispiel betrachten, und nicht der Inhalt.
Es sieht sauber aus, aber auch der durchschnittliche Toilettensitz und Türknauf
Nach meiner begrenzten Erfahrung habe ich nur sehr wenige Menschen gesehen, die tatsächlich in der Lage waren, Informationen, die von einem ternären Operator benötigt wurden, schnell auszuliefern. Vermeiden Sie dies, es sei denn, Sie sind sich zu 100% sicher, dass es besser ist. Es ist ein Schmerz zu beheben, wenn es auch abgehört ist, denke ich
int x = x == 1 ? 1 : 2
oder möglicherweiseint x = (x == 1) ? 1 : 2
x = x = 1;
überall und beschwerst dich dann, dass die Zuordnung zu kompliziert ist und vermieden werden sollte?