340 Stimmen

Wozu dienen geschweifte Klammern (d.h. {}) in einer einzeiligen if- oder Schleife?

Ich lese gerade einige Vorlesungsunterlagen meines C++-Dozenten, und er schrieb Folgendes:

  1. Einrückung verwenden // OK
  2. Verlassen Sie sich nie auf den Vorrang von Operatoren - Verwenden Sie immer Klammern // OK
  3. Verwenden Sie immer einen { }-Block - auch für eine einzelne Zeile // nicht OK Warum?
  4. Const-Objekt auf der linken Seite des Vergleichs // OK
  5. Vorzeichenlose Variablen, die >= 0 sind, verwenden // netter Trick
  6. Zeiger nach dem Löschen auf NULL setzen - Doppelter Löschschutz // nicht schlecht

Die 3. Technik ist mir nicht klar: Was würde ich gewinnen, wenn ich eine Zeile in a { ... } ?

Nehmen wir zum Beispiel diesen merkwürdigen Code:

int j = 0;
for (int i = 0 ; i < 100 ; ++i)
{
    if (i % 2 == 0)
    {
        j++;
    }
}

und ersetzen sie durch:

int j = 0;
for (int i = 0 ; i < 100 ; ++i)
    if (i % 2 == 0)
        j++;

Was ist der Vorteil der 1. Version?

20voto

Nemanja Trifunovic Punkte 23869

Meine 2c:

Einrückung verwenden

Offensichtlich

Verlassen Sie sich niemals auf den Vorrang von Operatoren - Verwenden Sie immer Klammern

Ich würde die Worte "nie" und "immer" nicht verwenden, aber im Allgemeinen halte ich diese Regel für nützlich. In einigen Sprachen (Lisp, Smalltalk) ist dies kein Problem.

Verwenden Sie immer einen { }-Block - auch für eine einzelne Zeile

Ich mache das nie und hatte noch nie ein einziges Problem, aber ich kann mir vorstellen, dass es für Schüler gut sein kann, vor allem, wenn sie vorher Python gelernt haben.

Konst. Objekt auf der linken Seite des Vergleichs

Yoda Bedingungen? Nein, bitte nicht. Das schadet der Lesbarkeit. Verwenden Sie einfach die maximale Warnstufe, wenn Sie Ihren Code kompilieren.

Vorzeichenlos für Variablen, die >= 0 sind

OK. Lustigerweise habe ich gehört, dass Stroustrup anderer Meinung ist.

Zeiger nach dem Löschen auf NULL setzen - Doppelter Löschschutz

Schlechter Rat! Haben Sie niemals einen Zeiger, der auf ein gelöschtes oder nicht existierendes Objekt zeigt.

19voto

Alok Save Punkte 196241

Sie ist intuitiv und leicht verständlich. Sie macht die Absicht klar.

Und es stellt sicher, dass der Code nicht kaputt geht, wenn ein neuer Benutzer unwissentlich die { , } beim Hinzufügen einer neuen Code-Anweisung.

14voto

Component 10 Punkte 9867

Um die sehr vernünftigen Vorschläge in den vorherigen Antworten zu ergänzen, möchte ich ein Beispiel anführen, das mir bei der Überarbeitung eines Codes begegnet ist, bei dem dies kritisch wird: Ich änderte eine sehr große Codebasis, um von einer API zu einer anderen zu wechseln. Die erste API hatte einen Aufruf zum Festlegen der Unternehmens-ID wie folgt:

setCompIds( const std::string& compId, const std::string& compSubId );

während für den Ersatz zwei Anrufe erforderlich waren:

setCompId( const std::string& compId );
setCompSubId( const std::string& compSubId );

Ich habe versucht, dies mit regulären Ausdrücken zu ändern, was sehr erfolgreich war. Wir haben den Code auch durch astyle Das hat die Lesbarkeit wirklich sehr verbessert. Dann entdeckte ich im Laufe des Überprüfungsprozesses, dass sich dies unter bestimmten Umständen änderte:

if ( condition )
   setCompIds( compId, compSubId );

Zu diesem:

if ( condition )
   setCompId( compId );
setCompSubId( compSubId );

was eindeutig nicht dem entspricht, was verlangt wurde. Ich musste noch einmal von vorne anfangen, indem ich die Ersetzung als vollständig innerhalb eines Blocks behandelte und dann manuell alles änderte, was am Ende komisch aussah (zumindest wäre es nicht falsch).

Ich stelle fest, dass astyle hat jetzt die Möglichkeit --add-brackets die es Ihnen ermöglicht Klammern hinzufügen, wo keine vorhanden sind und ich empfehle das sehr, wenn Sie sich jemals in der gleichen Lage befinden wie ich.

8voto

Lukasz Madon Punkte 14194

Ich verwende {} überall, außer in einigen wenigen Fällen, wo es offensichtlich ist. Die einzelne Zeile ist einer dieser Fälle:

if(condition) return; // OK

if(condition) // 
   return;    // and this is not a one-liner 

Es kann Ihnen schaden, wenn Sie eine Methode vor der Rückgabe hinzufügen. Die Einrückung zeigt an, dass die Rückgabe ausgeführt wird, wenn die Bedingung erfüllt ist, aber sie wird immer zurückgegeben.

Anderes Beispiel in C# mit using statment

using (D d = new D())  // OK
using (C c = new C(d))
{
    c.UseLimitedResource();
}

was gleichbedeutend ist mit

using (D d = new D())
{
    using (C c = new C(d))
    {
        c.UseLimitedResource();
    }
}

8voto

KeithS Punkte 67713

Das treffendste Beispiel, das mir einfällt:

if(someCondition)
   if(someOtherCondition)
      DoSomething();
else
   DoSomethingElse();

Welche if wird die else gepaart werden? Die Einrückung impliziert, dass die äußere if erhält die else aber das ist nicht das, was der Compiler sehen wird; die innen if erhält die else und die äußere if nicht. Sie müssten das wissen (oder sehen, wie es sich im Debugging-Modus verhält), um durch Inspektion herauszufinden, warum dieser Code Ihren Erwartungen nicht entspricht. Noch verwirrender wird es, wenn Sie Python kennen; in diesem Fall wissen Sie, dass die Einrückung Codeblöcke definiert, so dass Sie erwarten würden, dass der Code entsprechend der Einrückung ausgewertet wird. C# hingegen schert sich einen Dreck um Leerzeichen.

Abgesehen davon bin ich mit dieser Regel "immer Klammern verwenden" nicht besonders einverstanden. Sie macht den Code vertikal sehr unübersichtlich und erschwert das schnelle Durchlesen. Wenn die Anweisung ist:

if(someCondition)
   DoSomething();

... dann sollte es genau so geschrieben werden. Die Aussage "immer Klammern verwenden" klingt wie "mathematische Operationen immer mit Klammern umgeben". Das würde aus der sehr einfachen Aussage a * b + c / d en ((a * b) + (c / d)) Damit wird die Möglichkeit eingeführt, dass ein nahes Elternteil fehlt (der Fluch vieler Programmierer), und wozu? Die Reihenfolge der Operationen ist bekannt und gut erprobt, so dass die Klammern überflüssig sind. Sie würden Klammern nur verwenden, um eine andere Reihenfolge der Operationen zu erzwingen, als sie normalerweise angewendet würde: a * (b+c) / d zum Beispiel. Blockklammern sind ähnlich; verwenden Sie sie, um zu definieren, was Sie in Fällen tun wollen, in denen es von der Standardeinstellung abweicht und nicht "offensichtlich" ist (subjektiv, aber normalerweise ziemlich vernünftig).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X