2008-09-25 5 views
15

In C++ Initialisieren Sie eine Variable in einem if-Anweisung initialisieren können, etwa so:Pro/con: eine Variable in einer bedingten Anweisung

if (CThing* pThing = GetThing()) 
{ 
} 

Warum sollte man diese schlecht oder gut Stil in Betracht ziehen? Was sind die Vor- und Nachteile?

Persönlich mag ich diesen Stil, weil es den Umfang der pThing-Variable begrenzt, so dass es nie versehentlich verwendet werden kann, wenn es NULL ist. Allerdings Ich mag nicht, dass Sie dies nicht tun können:

if (CThing* pThing = GetThing() && pThing->IsReallySomeThing()) 
{ 
} 

Wenn es einen Weg gibt, die über Arbeit, bitte posten zu machen. Aber wenn das nicht möglich ist, möchte ich immer noch wissen warum. Diese

Question borrowed from here, similar topic but PHP.

Antwort

18

Wichtig ist, dass eine Deklaration in C++ kein Ausdruck ist.

bool a = (CThing* pThing = GetThing()); // not legit!! 

Sie können nicht beide eine Erklärung und Boolesche Logik in einer if-Anweisung, C++ Sprache Spec erlaubt zwar entweder ein Ausdruck oder eine Erklärung.

if(A *a = new A) 
{ 
    // this is legit and a is scoped here 
} 

Wie können wir wissen, ob a in einem Ausdruck zwischen einem Begriff und einem anderen definiert ist?

if((A *a = new A) && a->test()) 
{ 
    // was a really declared before a->test? 
} 

Beißen Sie die Kugel und verwenden Sie eine interne wenn. Die Bereichsregeln sind nützlich und Ihre Logik ist eindeutig:

if (CThing* pThing = GetThing()) 
{ 
    if(pThing->IsReallySomeThing()) 
    { 
    } 
} 
+1

"(A * a = neues A) && a-> test()" Dies ist kein Standard-C++. (-1) –

+0

Ich werde diese Antwort für die technische Ausführlichkeit akzeptieren. Die Diskussion darüber, was besser ist, ist in der Tat sehr subjektiv, ich bevorzuge den Stil von meinem ersten Post, aber mein TD will nicht, dass ich es benutze, also tue ich es nicht. Ich kann immer ein zusätzliches Paar Klammern verwenden, um den Umfang als Kompromiss zu begrenzen. – steffenj

2

sollte funktioniert nicht in C++ seit obwohl es short circuiting evaluation unterstützt. Vielleicht Versuchen Sie nicht, die folgenden:

if ((CThing* pThing = GetThing()) && (pThing->IsReallySomeThing())) 
{ 
} 

err .. Wesley Tarle's answer

+0

Ich werde es versuchen ... Ich erinnere mich, dass ich alle Arten von Klammerplatzierung ausprobiert habe, aber keiner würde funktionieren, obwohl sich die Compilerfehler je nach Klammern stark änderten. – steffenj

+0

"short circuit evaluation" ... ich habe das bisher nur als "früh raus" gewusst. Dieser ist neu für mich. – steffenj

2

Ein Grund sehe ich, dass das nicht tun normalerweise ist wegen der gemeinsamen Fehler von einem verpassten ‚=‘ in einem bedingten Prüfung. Ich benutze lint mit dem Fehler/Warnungen gesetzt, um diese zu fangen. Es wird dann über alle Zuweisungen innerhalb von Bedingungen schreien.

4

Über die Vorteile:

Es ist immer empfehlenswert, Variablen zu definieren, wenn Sie zuerst sie benötigen, nicht vor Zeile. Dies dient der besseren Lesbarkeit Ihres Codes, da man erkennen kann, was CThing ist, ohne zu scrollen und zu suchen, wo es definiert wurde.

Durch die Reduzierung des Bereichs auf eine Schleife/if-Block wird die Variable nach der Ausführung des Codeblocks nicht referenziert. Dies macht sie zu einem Kandidaten für Garbage Collection (wenn die Sprache diese Funktion unterstützt).

2

Nur ein FYI einige der älteren Microsoft C++ - Compiler (Visual Studios 6, und .NET 2003 denke ich) nicht in einigen Fällen die Scoping-Regel nicht ganz folgen.

Ich sollte außerhalb des Geltungsbereichs sein, aber das war/ist gültiger Code. Ich glaube, es wurde als Feature ausgespielt, aber meiner Meinung nach ist es nur Non-Compliance. Nicht an den Standards zu halten ist schlecht. Genau wie ein Webentwickler über IE und Firefox.

Kann jemand mit VS überprüfen und sehen, ob das noch gültig ist?

+1

Es ist eine Compiler-Option, "Geltendmachung von Geltungsbereich für Anweisung" oder so etwas. –

+2

Ja, es ist/Zc: forScope - "force-Konformität in for-Schleife Umfang". Zumindest in VS 2008. –

+0

Danke für die Überprüfung Jungs. Ich vermute, dass es standardmäßig aktiviert ist. –

0

Sie können die Zuweisung auch in einen zusätzlichen Satz von() einschließen, um die Warnmeldung zu verhindern.

0

Ich sehe das als eine Art von gefährlich. Der Code unten ist viel sicherer und die umschließenden Klammern beschränken den Umfang von pThing immer noch auf die von Ihnen gewünschte Weise.

Ich gehe davon aus, dass GetThing() manchmal NULL zurückgibt, weshalb ich diese lustige Klausel in die if() -Anweisung einfüge. Es verhindert, dass IsReallySomething() für einen NULL-Zeiger aufgerufen wird.

{ 
    CThing *pThing = GetThing(); 
    if(pThing ? pThing->IsReallySomeThing() : false) 
    { 
    // Do whatever 
    } 
} 
+2

C++ hat eine Kurzschlussauswertung, so dass "if (pThing && pthing-> IsReallySomeThing())" bereits garantiert, dass IsReallySomeThing() nicht aufgerufen wird, wenn pThing null ist. –

+0

Stimmen Sie mit Derek überein: true/false in einem?: Ist immer sauberer gemacht als ||/&& –

0

auch feststellen, dass, wenn Sie C++ Code schreiben Sie den Compiler Warnung über „=“ in einer bedingten Aussage machen wollen (das ist nicht Teil eine Deklaration) ein Fehler.

0

Es ist akzeptabel und gute Codierungspraxis. Allerdings würden Menschen, die nicht aus einem niedrigen Kodierungshintergrund stammen, wahrscheinlich anderer Meinung sein.

3
if (CThing* pThing = GetThing()) 

Es ist schlechter Stil, weil im Inneren des if Sie keinen Booleschen Ausdruck bereitstellt. Sie stellen eine CThing* zur Verfügung.

CThing* pThing = GetThing(); 
if (pThing != NULL) 

Das ist ein guter Stil.

Verwandte Themen