Interviewfrage: Welches wird schneller ausgeführt, if (flag==0)oder if (0==flag)? Warum?
if(flag = 0)zum Preis einer geringen Lesbarkeit.
Interviewfrage: Welches wird schneller ausgeführt, if (flag==0)oder if (0==flag)? Warum?
if(flag = 0)zum Preis einer geringen Lesbarkeit.
Antworten:
Ich habe noch keine richtige Antwort gesehen (und es gibt bereits einige) : Nawaz hat auf die benutzerdefinierte Falle hingewiesen . Und ich bedauere meine hastige Gegenstimme zur "dümmsten Frage", denn es scheint, dass viele es nicht richtig verstanden haben und es Raum für eine nette Diskussion über die Compileroptimierung gibt :)
Die Antwort ist:
Was ist
flagder Typ?
In dem Fall, in dem es sich flagtatsächlich um einen benutzerdefinierten Typ handelt. Dann kommt es darauf an, welche Überlast operator==ausgewählt ist. Natürlich kann es dumm erscheinen, dass sie nicht symmetrisch sind, aber es ist sicherlich erlaubt, und ich habe bereits andere Missbräuche gesehen.
Wenn flag es sich um ein eingebautes handelt, sollten beide die gleiche Geschwindigkeit annehmen.
Aus dem Wikipedia - Artikel auf x86, würde ich für eine Wette JxxAnweisung für die ifAussage: vielleicht eine JNZ(Sprung , wenn nicht gleich Null) oder ein Äquivalent.
Ich würde bezweifeln, dass der Compiler eine so offensichtliche Optimierung verpasst, selbst wenn die Optimierungen deaktiviert sind. Dies ist die Art von Dingen, für die Peephole Optimization entwickelt wurde.
BEARBEITEN: Wieder aufgetaucht, also fügen wir eine Baugruppe hinzu (LLVM 2.7 IR)
int regular(int c) {
if (c == 0) { return 0; }
return 1;
}
int yoda(int c) {
if (0 == c) { return 0; }
return 1;
}
define i32 @regular(i32 %c) nounwind readnone {
entry:
%not. = icmp ne i32 %c, 0 ; <i1> [#uses=1]
%.0 = zext i1 %not. to i32 ; <i32> [#uses=1]
ret i32 %.0
}
define i32 @yoda(i32 %c) nounwind readnone {
entry:
%not. = icmp ne i32 %c, 0 ; <i1> [#uses=1]
%.0 = zext i1 %not. to i32 ; <i32> [#uses=1]
ret i32 %.0
}
Auch wenn man nicht weiß, wie man das IR liest, denke ich, dass es selbsterklärend ist.
flagdas eine ganze Zahl oder ein Boolescher Wert sein muss. OTOH, eine Variable mit dem Namen flageines benutzerdefinierten Typs zu haben, ist an sich völlig falsch, IMHO
#includeRichtlinie verfügbar . Der Einfachheit halber, es beträgt in der Regel int, char, boolund dergleichen. Alle anderen Typen sind gesagt, dass benutzerdefiniert, dh sie existieren , weil sie das Ergebnis eines Benutzers sind erklärt sie: typedef, enum, struct, class. Zum Beispiel std::stringist benutzerdefiniert, obwohl Sie es sicherlich nicht selbst definiert haben :)
Gleicher Code für amd64 mit GCC 4.1.2:
.loc 1 4 0 # int f = argc;
movl -20(%rbp), %eax
movl %eax, -4(%rbp)
.loc 1 6 0 # if( f == 0 ) {
cmpl $0, -4(%rbp)
jne .L2
.loc 1 7 0 # return 0;
movl $0, -36(%rbp)
jmp .L4
.loc 1 8 0 # }
.L2:
.loc 1 10 0 # if( 0 == f ) {
cmpl $0, -4(%rbp)
jne .L5
.loc 1 11 0 # return 1;
movl $1, -36(%rbp)
jmp .L4
.loc 1 12 0 # }
.L5:
.loc 1 14 0 # return 2;
movl $2, -36(%rbp)
.L4:
movl -36(%rbp), %eax
.loc 1 15 0 # }
leave
ret
Es wird keinen Unterschied in Ihren Versionen geben.
Ich gehe davon aus, dass das typeFlag of kein benutzerdefinierter Typ ist, sondern ein integrierter Typ. Aufzählung ist Ausnahme!. Sie können Enum so behandeln, als wäre es eingebaut. Tatsächlich handelt es sich um integrierte Werte!
Falls es sich um einen benutzerdefinierten Typ handelt (außer enum), hängt die Antwort vollständig davon ab, wie Sie den Operator überladen haben ==. Beachten Sie, dass Sie überladen müssen, ==indem Sie zwei Funktionen definieren, eine für jede Ihrer Versionen!
Es gibt absolut keinen Unterschied.
Sie können Punkte bei der Beantwortung dieser Interviewfrage sammeln, indem Sie sich auf die Beseitigung von Zuweisungs- / Vergleichstipps beziehen:
if (flag = 0) // typo here
{
// code never executes
}
if (0 = flag) // typo and syntactic error -> compiler complains
{
// ...
}
Während es wahr ist, dass zB ein C-Compiler im Fall des ersteren ( flag = 0) warnt , gibt es keine solchen Warnungen in PHP, Perl oder Javascript oder <insert language here>.
In Bezug auf die Geschwindigkeit wird es absolut keinen Unterschied geben. Warum sollte es geben?
x == 0möglicherweise verwendet wird, aber 0 == xmöglicherweise einen normalen Vergleich verwendet. Ich habe gesagt, es müsste verzögert werden.
virtual operator==(int)in einem benutzerdefinierten Typ?
Nun, es gibt einen Unterschied, wenn flag ein benutzerdefinierter Typ ist
struct sInt
{
sInt( int i ) : wrappedInt(i)
{
std::cout << "ctor called" << std::endl;
}
operator int()
{
std::cout << "operator int()" << std::endl;
return wrappedInt;
}
bool operator==(int nComp)
{
std::cout << "bool operator==(int nComp)" << std::endl;
return (nComp == wrappedInt);
}
int wrappedInt;
};
int
_tmain(int argc, _TCHAR* argv[])
{
sInt s(0);
//in this case this will probably be faster
if ( 0 == s )
{
std::cout << "equal" << std::endl;
}
if ( s == 0 )
{
std::cout << "equal" << std::endl;
}
}
Im ersten Fall (0 == s) wird der Konvertierungsoperator aufgerufen und das zurückgegebene Ergebnis mit 0 verglichen. Im zweiten Fall wird der Operator == aufgerufen.
Wenn Sie Zweifel haben, messen Sie es und erfahren Sie die Wahrheit.
Sie sollten in Bezug auf die Geschwindigkeit genau gleich sein.
Beachten Sie jedoch, dass einige Leute die Konstante in Gleichheitsvergleichen links verwenden (die sogenannten "Yoda-Bedingungen"), um alle Fehler zu vermeiden, die auftreten können, wenn Sie =(Zuweisungsoperator) anstelle von ==(Gleichheitsvergleichsoperator) schreiben . Da das Zuweisen zu einem Literal einen Kompilierungsfehler auslöst, wird diese Art von Fehler vermieden.
if(flag=0) // <--- typo: = instead of ==; flag is now set to 0
{
// this is never executed
}
if(0=flag) // <--- compiler error, cannot assign value to literal
{
}
Auf der anderen Seite finden die meisten Leute "Yoda-Bedingungen" seltsam und nervig, zumal die Klasse der Fehler, die sie verhindern, auch durch die Verwendung geeigneter Compiler-Warnungen erkannt werden kann.
if(flag=0) // <--- warning: assignment in conditional expression
{
}
Wie andere gesagt haben, gibt es keinen Unterschied.
0muss bewertet werden. flagmuss bewertet werden. Dieser Vorgang dauert genauso lange, egal auf welcher Seite sie platziert sind.
Die richtige Antwort wäre: Sie sind beide gleich schnell.
Sogar die Ausdrücke if(flag==0)und if(0==flag)haben die gleiche Anzahl von Zeichen! Wenn einer von ihnen als geschrieben if(flag== 0)wäre, hätte der Compiler einen zusätzlichen Speicherplatz zum Parsen, sodass Sie einen berechtigten Grund hätten, auf die Kompilierungszeit hinzuweisen.
Aber da es so etwas nicht gibt, gibt es absolut keinen Grund, warum einer schneller sein sollte als der andere. Wenn es einen Grund gibt, macht der Compiler einige sehr, sehr seltsame Dinge mit dem generierten Code ...
Welches schnell ist, hängt davon ab, welche Version von == Sie verwenden. Hier ist ein Ausschnitt, der zwei mögliche Implementierungen von == verwendet. Je nachdem, ob Sie x == 0 oder 0 == x aufrufen, wird eine der beiden ausgewählt.
Wenn Sie nur einen POD verwenden, sollte dies in Bezug auf die Geschwindigkeit keine Rolle spielen.
#include <iostream>
using namespace std;
class x {
public:
bool operator==(int x) { cout << "hello\n"; return 0; }
friend bool operator==(int x, const x& a) { cout << "world\n"; return 0; }
};
int main()
{
x x1;
//int m = 0;
int k = (x1 == 0);
int j = (0 == x1);
}
Nun, ich stimme allen Aussagen in den Kommentaren zum OP voll und ganz zu, um der Übung willen:
Wenn der Compiler nicht klug genug ist (in der Tat sollten Sie ihn nicht verwenden) oder die Optimierung deaktiviert ist, x == 0könnte er jump if zerowährenddessen zu einer nativen Assembly- Anweisung kompiliert werden0 == x ein allgemeinerer (und kostspieligerer) Vergleich numerischer Werte möglich ist.
Trotzdem würde ich nicht gerne für einen Chef arbeiten, der so denkt ...
Sicherlich kein Unterschied in Bezug auf die Ausführungsgeschwindigkeit. Der Zustand muss in beiden Fällen gleich bewertet werden.
Ich denke, die beste Antwort ist "In welcher Sprache ist dieses Beispiel?"
Die Frage hat die Sprache nicht angegeben und ist sowohl mit 'C' als auch mit 'C ++' gekennzeichnet. Eine genaue Antwort benötigt mehr Informationen.
Es ist eine miese Programmierfrage, aber es könnte eine gute Frage in der verschlagenen Abteilung "Geben wir dem Befragten genug Seil, um sich entweder aufzuhängen oder eine Baumschaukel zu bauen" sein. Das Problem bei solchen Fragen ist, dass sie normalerweise von Interviewer zu Interviewer aufgeschrieben und weitergegeben werden, bis sie an Leute gelangen, die sie nicht wirklich aus allen Blickwinkeln verstehen.
Erstellen Sie zwei einfache Programme auf die vorgeschlagenen Arten.
Bauen Sie die Codes zusammen. Schauen Sie sich die Versammlung an und Sie können beurteilen, aber ich bezweifle, dass es einen Unterschied gibt!
Die Interviews werden niedriger als je zuvor.
Abgesehen davon (ich denke tatsächlich, dass jeder anständige Compiler diese Frage in Frage stellen wird, da sie optimiert wird) verhindert die Verwendung von 0 == flag over flag == 0 den Tippfehler, bei dem Sie eines der = vergessen (dh wenn Sie versehentlich tippen) flag = 0 wird kompiliert, aber 0 = flag wird nicht), was ich für einen Fehler halte, den jeder an dem einen oder anderen Punkt gemacht hat ...