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?

1voto

John Punkte 3482

Es ist am besten, den Zeiger auf NULL zu setzen, wenn Sie mit ihm fertig sind.

Hier ist ein Beispiel dafür:

Die Klasse A hat folgende Aufgaben:

  1. Weist einen Speicherblock zu
  2. Einige Zeit später wird dieser Speicherblock gelöscht, ohne dass der Zeiger auf NULL gesetzt wird.

Die Klasse B hat folgende Aufgaben

  1. Weist Speicher zu (und erhält in diesem Fall zufällig denselben Speicherblock, der von Klasse A gelöscht wurde).

Zu diesem Zeitpunkt haben sowohl Klasse A als auch Klasse B Zeiger, die auf denselben Speicherblock zeigen. Für Klasse A existiert dieser Speicherblock nicht mehr, da sie ihn nicht mehr benötigt.

Betrachten Sie das folgende Problem:

Was wäre, wenn es einen logischen Fehler in Klasse A gäbe, der dazu führte, dass sie in einen Speicher schreibt, der jetzt zu Klasse B gehört?

In diesem speziellen Fall erhalten Sie keine Fehlermeldung, da die Speicheradresse legal ist, während Klasse A nun effektiv Daten der Klasse B beschädigt.

Klasse B kann schließlich abstürzen, wenn sie auf unerwartete Werte stößt, und wenn sie abstürzt, werden Sie wahrscheinlich viel Zeit damit verbringen, diesen Fehler in Klasse B zu suchen, obwohl das Problem in Klasse A liegt.

Hätten Sie den gelöschten Speicherzeiger auf NULL gesetzt, hätten Sie einen Ausnahmefehler erhalten, sobald ein Logikfehler in Klasse A versucht, in den NULL-Zeiger zu schreiben.

Wenn Sie über den Logikfehler mit doppeltem Löschen besorgt sind, wenn Zeiger zum zweiten Mal NULL sind, dann fügen Sie assert für diese.

1voto

ST3 Punkte 8392

Ich muss zugeben, dass ich nicht immer die {} für einzelne Zeilen, aber es ist eine gute Übung.

  • Angenommen, Sie schreiben einen Code ohne Klammern, der wie folgt aussieht:

    for (int i = 0; i < 100; ++i) for (int j = 0; j < 100; ++j) DoSingleStuff();

Und nach einiger Zeit wollen Sie weitere Dinge in die j Schleife, und Sie tun dies einfach durch Ausrichtung und vergessen, Klammern hinzuzufügen.

  • Die Speicherfreigabe ist schneller. Nehmen wir an, Sie haben einen großen Bereich und erstellen darin große Arrays (ohne new damit sie auf dem Stapel liegen). Diese Arrays werden aus dem Speicher entfernt, sobald Sie den Bereich verlassen. Es ist jedoch möglich, dass Sie das Array an einer Stelle verwenden und es eine Zeit lang auf dem Stack liegt und eine Art Müll ist. Da ein Stack eine begrenzte und recht kleine Größe hat, ist es möglich, die Größe des Stacks zu überschreiten. Daher ist es in manchen Fällen besser, zu schreiben {} um dies zu verhindern. Hinweis dass dies nicht für eine einzelne Zeile, sondern für solche Situationen gilt:

    if (...) { //SomeStuff... {//wir haben kein if, while, etc. //SonstigesZeug } //EinigeWeitereSachen }

  • Die dritte Art der Verwendung ist ähnlich wie die zweite. Es geht nur nicht darum, den Stapel sauberer zu machen, sondern darum öffnen einige Funktionen. Wenn Sie mutex Bei langen Funktionen ist es in der Regel besser, das Sperren und Entsperren kurz vor dem Zugriff auf Daten und kurz nach Beendigung des Lesens/Schreibens vorzunehmen. Hinweis : Dieser Weg wird verwendet, wenn Sie eine eigene Klasse oder Struktur mit einem Konstruktor und Destruktor haben, um den Speicher zu sperren.

  • Und noch etwas:

    wenn (...) if (...) SomeStuff(); sonst SomeOtherStuff(); // Geht zum zweiten if, aber die Ausrichtung zeigt, dass es auf dem ersten steht...

Alles in allem kann ich nicht sagen, wie man am besten vorgeht, wenn man {} ist für eine einzige Zeile, aber das ist nicht schlimm.

Wenn Sie Code kompilieren Klammern für eine einzige Zeile macht nichts, aber wenn Ihr Code interpretiert wird es verlangsamt den Code sehr sehr leicht. Sehr geringfügig.

1voto

supercat Punkte 72939

Es gibt eine Reihe von Möglichkeiten, Kontrollanweisungen zu schreiben; bestimmte Kombinationen davon können nebeneinander bestehen, ohne die Lesbarkeit zu beeinträchtigen, aber andere Kombinationen werden Probleme verursachen. Der Stil

if (condition)
  statement;

lässt sich gut mit einigen der anderen Arten, Kontrollanweisungen zu schreiben, vereinbaren, mit anderen jedoch nicht so gut. Wenn mehrzeilige kontrollierte Anweisungen geschrieben werden als:

if (condition)
{
  statement;
  statement;
}

dann wird visuell ersichtlich sein, welche if Anweisungen eine einzelne Zeile steuern und welche Anweisungen mehrere Zeilen steuern. Wenn jedoch mehrzeilige if Anweisungen werden wie folgt geschrieben:

if (condition) {
  statement;
  statement;
}

dann ist die Wahrscheinlichkeit, dass jemand versucht, eine Single-Statement-Anweisung zu erweitern if Konstruktionen ohne Hinzufügen der erforderlichen Klammern kann viel höher sein.

Die Zeile "Ein-Satz-auf-dem-Nächsten if Anweisung kann auch problematisch sein, wenn die Codebasis in erheblichem Umfang von der Form

if (condition) statement;

Ich selbst bevorzuge, dass die Aussage in einer eigenen Zeile steht, was im Allgemeinen die Lesbarkeit verbessert, außer in Fällen, in denen es viele if Anweisungen mit ähnlichen Kontrollblöcken, z. B.

if (x1 > xmax) x1 = xmax;
if (x1 < xmin) x1 = xmin;
if (x2 > xmax) x2 = xmax;
if (x2 < xmin) x2 = xmin;
etc.

In diesem Fall werde ich in der Regel vor und nach solchen Gruppen von if Anweisungen mit einer Leerzeile, um sie visuell von anderem Code zu trennen. Eine Reihe von Anweisungen, die alle mit if in der gleichen Einrückung wird dann ein cl

1voto

Michiel Cornille Punkte 2027

A

if(guardClause)
      throw new SomeException(..)

U

e

if(someCondition)
{
   doTechnicalThingX();
   doTechnicalThingY();
   doTechnicalThingZ();
}

S

if(someCondition)
    doFunctionalThingA();

S

I

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