Google Style Guide in C ++. Teil 10

Teil 1. Einführung
...
Teil 9. Kommentare
Teil 10. Formatierung
...


Dieser Artikel ist eine Übersetzung eines Teils des Google Style Guides in C ++ ins Russische.
Originalartikel (Gabel auf Github), aktualisierte Übersetzung .

Formatierung


Der Codierungs- und Formatierungsstil ist beliebig, aber das Projekt ist viel einfacher zu verwalten, wenn alle dem gleichen Stil folgen. Obwohl jemand möglicherweise nicht mit allen Regeln einverstanden ist (oder das verwendet, was er gewohnt ist), ist es sehr wichtig, dass jeder die gleichen Regeln befolgt, um den Code eines anderen leicht lesen und verstehen zu können.
Für die korrekte Formatierung haben wir eine Einstellungsdatei für Emacs erstellt .

Linienlänge


Es ist ratsam, die Länge der Codezeilen auf 80 Zeichen zu beschränken.
Diese Regel ist etwas umstritten, aber der Großteil des vorhandenen Codes entspricht diesem Prinzip, und wir unterstützen es auch.

Für
Anhänger der Regel heißt es, dass keine längeren Linien benötigt werden und eine ständige Anpassung der Fenstergröße mühsam ist. Außerdem platzieren einige Fenster mit Code nebeneinander und können die Breite der Fenster nicht willkürlich erhöhen. Gleichzeitig ist eine Breite von 80 Zeichen ein historischer Standard. Warum sollte man ihn ändern?

Die

andere Seite behauptet, dass lange Zeilen die Lesbarkeit des Codes verbessern können. 80 Zeichen ist ein Relikt des Mainframes der 1960er Jahre. Moderne Bildschirme können durchaus längere Zeilen anzeigen.

Ein Urteil von

80 Zeichen ist das Maximum.

Eine Zeichenfolge kann ein Limit von 80 Zeichen überschreiten, wenn:

  • . , URL-, 80 .
  • /, 80 . , .
  • include.
  • using

-ASCII


Nicht-ASCII-Zeichen sollten so selten wie möglich verwendet werden. Die Codierung sollte UTF-8 sein.
Sie müssen keine Zeichenfolgen fest codieren, um sie dem Benutzer anzuzeigen (auch nicht in Englisch). Daher sollten Nicht-ASCII-Zeichen selten sein. In einigen Fällen ist es jedoch zulässig, solche Wörter in den Code aufzunehmen. Wenn der Code beispielsweise Datendateien analysiert (mit nicht englischer Codierung), ist es möglich, nationale Begrenzungswörter in den Code aufzunehmen. In einem allgemeineren Fall kann der Unit-Test-Code nationale Zeichenfolgen enthalten. In diesen Fällen sollte die UTF-8-Codierung verwendet werden, z Es wird von den meisten Dienstprogrammen verstanden (die nicht nur ASCII verstehen).

Hex ist auch gültig, insbesondere wenn es die Lesbarkeit verbessert. Zum Beispiel "\ xEF \ xBB \ xBF" oder u8 "\ uFEFF"- Ein untrennbarer Raum mit der Länge Null in Unicode, der nicht im richtigen UTF-8-Text angezeigt werden sollte.

Verwenden Sie das Präfix u8, damit Literale wie \ uXXXX in UTF-8 codiert werden. Verwenden Sie es nicht für Zeilen, die Nicht-ASCII-Zeichen enthalten, die bereits in UTF-8 codiert sind. Sie können ungeschickten Text erhalten, wenn der Compiler den Quellcode nicht als UTF-8 erkennt.

Vermeiden Sie seitdem die Verwendung von C ++ 11- Zeichen char16_t und char32_t Sie werden für Nicht-UTF-8-Leitungen benötigt. Verwenden Sie aus den gleichen Gründen nicht wchar_t (außer wenn Sie mit der Windows-API mit wchar_t arbeiten ).

Leerzeichen gegen Tabulatoren


Verwenden Sie nur Leerzeichen zum Einrücken. 2 Leerzeichen für einen Einzug.
Wir verwenden Leerzeichen zum Einrücken. Verwenden Sie keine Tabulatoren in Ihrem Code. Konfigurieren Sie Ihren Editor so, dass beim Drücken der Tabulatortaste Leerzeichen eingefügt werden.

Funktionsdeklarationen und Definitionen


Versuchen Sie, den Typ des Rückgabewerts, den Namen der Funktion und ihre Parameter in eine Zeile zu setzen (wenn alles passt). Teilen Sie eine zu lange Liste von Parametern in Zeilen auf, genau wie Argumente in einem Funktionsaufruf.

Ein Beispiel für das richtige Funktionsdesign:

ReturnType ClassName::FunctionName(Type par_name1, Type par_name2) {
  DoSomething();
  ...
}

Wenn eine Zeile nicht ausreicht:

ReturnType ClassName::ReallyLongFunctionName(Type par_name1, Type par_name2,
                                             Type par_name3) {
  DoSomething();
  ...
}

oder, wenn der erste Parameter auch nicht passt:

ReturnType LongClassName::ReallyReallyReallyLongFunctionName(
    Type par_name1,  //  4 
    Type par_name2,
    Type par_name3) {
  DoSomething();  //  2 
  ...
}

Ein paar Anmerkungen:

  • Wählen Sie gute Namen für Optionen.
  • Sie können den Parameternamen weglassen, wenn er nicht in der Funktionsdefinition verwendet wird.
  • , , . .
  • .
  • .
  • .
  • . .
  • , , .
  • .
  • .
  • — 2 .
  • Wenn Sie Parameter in eine andere Zeile übertragen, rücken Sie 4 Leerzeichen ein.

Sie können den Namen nicht verwendeter Parameter weglassen, wenn dies aus dem Kontext ersichtlich ist:

class Foo {
 public:
  Foo(const Foo&) = delete;
  Foo& operator=(const Foo&) = delete;
};

Nicht verwendete Parameter mit nicht offensichtlichem Kontext sollten in der Funktionsdefinition auskommentiert werden:

class Shape {
 public:
  virtual void Rotate(double radians) = 0;
};

class Circle : public Shape {
 public:
  void Rotate(double radians) override;
};

void Circle::Rotate(double /*radians*/) {}

//   -  -     ,
//    .
void Circle::Rotate(double) {}

Versuchen Sie, Attribute und Makros am Anfang einer Ankündigung oder Funktionsdefinition
bis zum Typ des Rückgabewerts zu verwenden:
ABSL_MUST_USE_RESULT bool IsOk();

Lambdas


Formatieren Sie die Parameter und den Hauptteil des Ausdrucks wie eine reguläre Funktion. Die Liste der erfassten Variablen ähnelt einer normalen Liste.

Setzen Sie zum Erfassen von Variablen als Referenz kein Leerzeichen zwischen das kaufmännische Und (&) und den Variablennamen.

int x = 0;
auto x_plus_n = [&x](int n) -> int { return x + n; }

Kurze Lambdas können direkt als Argument für eine Funktion verwendet werden.

std::set<int> blacklist = {7, 8, 9};
std::vector<int> digits = {3, 9, 1, 8, 4, 7, 1};
digits.erase(std::remove_if(digits.begin(), digits.end(), [&blacklist](int i) {
               return blacklist.find(i) != blacklist.end();
             }),
             digits.end());

Gleitkommazahlen


Gleitkommazahlen sollten immer einen Dezimalpunkt und Zahlen auf beiden Seiten haben (auch bei Exponentialschreibweise). Dieser Ansatz verbessert die Lesbarkeit: Alle Gleitkommazahlen haben dasselbe Format, Sie verwechseln es nicht mit einer Ganzzahl, und die Zeichen E e der Exponentialschreibweise können nicht für hexadezimale Ziffern verwendet werden. Denken Sie daran, dass eine Zahl in Exponentialschreibweise keine Ganzzahl ist.

float f = 1.f;
long double ld = -.5L;
double d = 1248e6;

float f = 1.0f;
float f2 = 1;   //  
long double ld = -0.5L;
double d = 1248.0e6;

Funktionsaufruf


Schreiben Sie entweder den gesamten Funktionsaufruf in eine Zeile oder setzen Sie Argumente in eine neue Zeile. Und der Einzug kann entweder beim ersten Argument oder bei 4 Leerzeichen stehen. Versuchen Sie, die Anzahl der Zeilen zu minimieren, und platzieren Sie einige Argumente in jeder Zeile.

Funktionsaufrufformat:

bool result = DoSomething(argument1, argument2, argument3);

Wenn die Argumente nicht in eine Zeile passen, teilen wir sie in mehrere Zeilen auf und jede nachfolgende Zeile wird mit dem ersten Argument ausgerichtet. Fügen Sie keine Leerzeichen zwischen Klammern und Argumenten ein:

bool result = DoSomething(averyveryveryverylongargument1,
                          argument2, argument3);


Es ist zulässig, Argumente in mehreren Zeilen mit einem Einzug von 4 Leerzeichen zu platzieren:
if (...) {
  ...
  ...
  if (...) {
    bool result = DoSomething(
        argument1, argument2,  //  4 
        argument3, argument4);
    ...
  }

Versuchen Sie, mehrere Argumente pro Zeile zu platzieren, um die Anzahl der Zeilen pro Funktionsaufruf zu verringern (wenn dies die Lesbarkeit nicht beeinträchtigt). Einige Leute denken, dass die Formatierung nur eines Arguments pro Zeile besser lesbar ist und das Bearbeiten von Argumenten erleichtert. Wir konzentrieren uns jedoch hauptsächlich auf Codeleser (nicht auf die Bearbeitung), daher bieten wir eine Reihe von Ansätzen zur Verbesserung der Lesbarkeit an.

Wenn mehrere Argumente in derselben Zeile die Lesbarkeit beeinträchtigen (aufgrund der Komplexität oder Komplexität der Ausdrücke), versuchen Sie, "sprechende" Variablen für die Argumente zu erstellen:

int my_heuristic = scores[x] * y + bases[x];
bool result = DoSomething(my_heuristic, x, y, z);

Oder setzen Sie das komplexe Argument in eine separate Zeile und fügen Sie einen erklärenden Kommentar hinzu:

bool result = DoSomething(scores[x] * y + bases[x],  //  
                          x, y, z);

Wenn der Funktionsaufruf immer noch Argumente enthält, die in eine separate Zeile eingefügt werden sollen, platzieren Sie ihn. Eine Lösung sollte auf der Verbesserung der Lesbarkeit des Codes basieren.

Argumente bilden manchmal eine Struktur. Formatieren Sie in diesem Fall die Argumente entsprechend der erforderlichen Struktur:

//     3x3
my_widget.Transform(x1, x2, x3,
                    y1, y2, y3,
                    z1, z2, z3);


Formatieren einer Initialisierungsliste


Formatieren Sie die Initialisierungsliste wie einen Funktionsaufruf.

Wenn die Liste in Klammern dem Namen folgt (z. B. dem Namen eines Typs oder einer Variablen), formatieren Sie {} so, als wäre es ein Funktionsaufruf mit diesem Namen. Auch wenn es keinen Namen gibt, denken Sie daran, dass er nur leer ist.

//      .
return {foo, bar};
functioncall({foo, bar});
std::pair<int, int> p{foo, bar};

//     .
SomeFunction(
    {"assume a zero-length name before {"},
    some_other_function_parameter);
SomeType variable{
    some, other, values,
    {"assume a zero-length name before {"},
    SomeOtherType{
        "Very long string requiring the surrounding breaks.",
        some, other values},
    SomeOtherType{"Slightly shorter string",
                  some, other, values}};
SomeType variable{
    "This is too long to fit all in one line"};
MyType m = {  // Here, you could also break before {.
    superlongvariablename1,
    superlongvariablename2,
    {short, interior, list},
    {interiorwrappinglist,
     interiorwrappinglist2}};

Bedingungen


Versuchen Sie, keine Leerzeichen in die Innenseite der Klammern einzufügen. Platzieren Sie if und else in verschiedenen Zeilen.

Es gibt zwei Ansätze zum Formatieren von Bedingungen. Einer lässt Leerzeichen zwischen Klammern und einer Bedingung zu, der andere nicht.

Die bevorzugte Option ohne Leerzeichen. Eine andere Option ist ebenfalls gültig, aber konsistent . Wenn Sie vorhandenen Code ändern, verwenden Sie das Format, das bereits im Code enthalten ist. Wenn Sie neuen Code schreiben, verwenden Sie das Format wie die Dateien im selben Verzeichnis oder das Projektformat. Wenn Sie sich nicht sicher sind, fügen Sie keine Leerzeichen hinzu.

if (condition) {  //    
  ...  //  2 
} else if (...) {  // 'else'      
  ...
} else {
  ...
}

Wenn Sie ein Leerzeichenformat verwenden:

if ( condition ) {  //   
  ...  //  2 
} else {  // 'else'      
  ...
}

Beachten Sie, dass in jedem Fall ein Abstand zwischen if und der öffnenden Halterung vorhanden sein muss. Sie benötigen auch einen Abstand zwischen der schließenden Klammer und der geschweiften Klammer (falls vorhanden).

if(condition) {   //  -    'if'
if (condition){   //  -    {
if(condition){    //  

if (condition) {  //   -     'if'   {

Kurze Bedingungen können in eine Zeile geschrieben werden, wenn dies die Lesbarkeit verbessert. Verwenden Sie diese Option nur, wenn die Zeile kurz ist und die Bedingung keinen anderen Abschnitt enthält .

if (x == kFoo) return new Foo();
if (x == kBar) return new Bar();

Verwenden Sie die verkürzte Version nicht, wenn es einen anderen Abschnitt gibt :

//  -    ,   'else'
if (x) DoThis();
else DoThat();

Normalerweise sind Zahnspangen für einen kurzen Zustand nicht erforderlich, aber sie sind akzeptabel. Komplizierte Bedingungen oder Code lassen sich auch besser mit geschweiften Klammern lesen. Es wird oft , dass sie erforderlich , wenn mit Klammern sein.

if (condition)
  DoSomething();  //  2 

if (condition) {
  DoSomething();  //  2 
}

Und wenn ein Teil der Bedingung geschweifte Klammern verwendet, geben Sie auch den zweiten mit ihnen aus:

//  -    'if',  'else' - 
if (condition) {
  foo;
} else
  bar;

//  -    'else',  'if' - 
if (condition)
  foo;
else {
  bar;
}


//  -     'if'   'else'
if (condition) {
  foo;
} else {
  bar;
}

Schleifen und Schalter


Das Schalterkonstrukt kann Klammern für Blöcke verwenden. Beschreiben Sie nicht triviale Übergänge zwischen Optionen. Klammern sind für einzelne Ausdrucksschleifen optional. Eine leere Schleife sollte entweder einen leeren Körper in Klammern verwenden oder fortfahren .

Die Fall - Blöcke in dem Schalter können entweder mit geschweiften Klammern sein, oder ohne sie (nach Wahl). Wenn Klammern verwendet werden, verwenden Sie das unten beschriebene Format.

Es wird empfohlen, zum Standardabschnitt in switch zu wechseln . Dies ist bei Verwendung einer Aufzählung nicht erforderlich, und der Compiler gibt möglicherweise eine Warnung aus, wenn nicht alle Werte verarbeitet werden. Wenn der Standardabschnitt nicht ausgeführt werden soll, konfigurieren Sie ihn als Fehler. Zum Beispiel:

switch (var) {
  case 0: {  //  2 
    ...      //  4 
    break;
  }
  case 1: {
    ...
    break;
  }
  default: {
    assert(false);
  }
}

Der Übergang von einem Etikett zum nächsten sollte mit dem Makro ABSL_FALLTHROUGH_INTENDED markiert werden . (definiert in absl / base / macros.h ).
Platziere ABSL_FALLTHROUGH_INTENDED; an dem Punkt, an dem der Übergang sein wird. Eine Ausnahme von dieser Regel bilden aufeinanderfolgende Beschriftungen ohne Code. In diesem Fall muss nichts markiert werden.

switch (x) {
  case 41:  //  
  case 43:
    if (dont_be_picky) {
      //    ( )    
      ABSL_FALLTHROUGH_INTENDED;
    } else {
      CloseButNoCigar();
      break;
    }
  case 42:
    DoSomethingSpecial();
    ABSL_FALLTHROUGH_INTENDED;
  default:
    DoSomethingGeneric();
    break;
}

Halterungen sind für Einzelschleifen optional.

for (int i = 0; i < kSomeNumber; ++i)
  printf("I love you\n");

for (int i = 0; i < kSomeNumber; ++i) {
  printf("I take it back\n");
}

Eine leere Schleife sollte entweder als Klammerpaar oder als Fortsetzung ohne Klammern gestaltet werden. Verwenden Sie kein einzelnes Semikolon.

while (condition) {
  //    false
}
for (int i = 0; i < kSomeNumber; ++i) {}  // .      -   
while (condition) continue;  //  - continue     

while (condition);  //  -     do/while

Zeiger und Links


Um '.' und '->' setzen keine Leerzeichen. Der Dereferenzierungs- oder Erfassungsoperator muss ohne Leerzeichen sein.

Im Folgenden finden Sie Beispiele für die ordnungsgemäße Formatierung von Ausdrücken mit Zeigern und Links:

x = *p;
p = &x;
x = r.y;
x = r->y;

Hinweis:

  • '.' und '->' werden ohne Leerzeichen verwendet.
  • Die Operatoren * oder & werden nicht durch Leerzeichen getrennt.

Wenn Sie eine Variable oder ein Argument deklarieren, können Sie '*' sowohl für den Typ als auch für den Namen einfügen:

// ,   *, &
char *c;
const std::string &str;

// ,   *, &
char* c;
const std::string& str;

Versuchen Sie, einen einzelnen Stil in der Codedatei zu verwenden. Verwenden Sie beim Ändern einer vorhandenen Datei die verwendete Formatierung.

Es dürfen mehrere Variablen in einem Ausdruck deklariert werden. Verwenden Sie jedoch nicht mehrere Deklarationen mit Zeigern oder Links - dies kann missverstanden werden.

//  - 
int x, y;

int x, *y;  //  -      &  *
char * c;  //  -     *
const std::string & str;  //  -     &

Logische Ausdrücke


Wenn der logische Ausdruck sehr lang ist (den typischen Wert überschreitet), verwenden Sie einen einzelnen Ansatz, um den Ausdruck in Zeilen zu unterteilen.

Zum Beispiel befindet sich hier beim Umschließen der AND-Operator am Ende der Zeile:

if (this_one_thing > this_other_thing &&
    a_third_thing == a_fourth_thing &&
    yet_another && last_one) {
  ...
}

Beachten Sie, dass der Code (gemäß dem Beispiel) aufgeteilt wird, sodass && und der AND-Operator die Zeile vervollständigen. Dieser Stil wird häufiger mit Google-Code verwendet, obwohl die Position der Operatoren am Zeilenanfang ebenfalls akzeptabel ist. Sie können auch zusätzliche Klammern hinzufügen, um die Lesbarkeit zu verbessern. Beachten Sie, dass die Verwendung von Operatoren in Form von Interpunktion (wie && und ~ ) der Verwendung von Operatoren in Form der Wörter und und compl vorzuziehen ist .

Rückgabewerte


Fügen Sie einfache return-Anweisungen nicht in Klammern ein.

Verwenden Sie im Gegenzug Klammern. nur wenn Sie sie in einem Ausdruck der Form x = expr; .

return result;                  //   -  
//  - .    
return (some_long_condition &&
        another_condition);

return (value);                // . ,      var = (value);
return(result);                // . return -   !

Variablen und Arrays initialisieren


Was zu verwenden ist: = , () oder
{} ist Ihre Wahl.

Sie können zwischen den Optionen = ,
() und {} wählen . Die folgenden Codebeispiele sind korrekt:

int x = 3;
int x(3);
int x{3};
std::string name = "Some Name";
std::string name("Some Name");
std::string name{"Some Name"};

Seien Sie vorsichtig, wenn Sie die Initialisierungsliste {...} für einen Typ verwenden, der einen Konstruktor mit std :: initializer_list hat .

Der Compiler bevorzugt die Verwendung des Konstruktors std :: initializer_list , wenn eine Liste in geschweiften Klammern steht . Beachten Sie, dass leere geschweifte Klammern {} ein Sonderfall sind und der Standardkonstruktor aufgerufen wird (falls verfügbar). Um einen Konstruktor ohne std :: initializer_list explizit zu verwenden , verwenden Sie Klammern anstelle von geschweiften Klammern.

std::vector<int> v(100, 1);  //    
std::vector<int> v{100, 1};  //   2- : 100  1


Außerdem verbietet die Konstruktion mit geschweiften Klammern eine Reihe von Transformationen ganzzahliger Typen (Transformationen mit abnehmender Genauigkeit). Und Sie können Kompilierungsfehler bekommen.

int pi(3.14);  // : pi == 3
int pi{3.14};  //  : "" 

Präprozessor-Direktiven


Das Zeichen # (Zeichen der Präprozessor-Direktive) sollte am Anfang der Zeile stehen.

Selbst wenn sich die Präprozessor-Direktive auf den eingebetteten Code bezieht, werden Direktiven am Anfang der Zeile geschrieben.

//  -    
  if (lopsided_score) {
#if DISASTER_PENDING      //  -    
    DropEverything();
# if NOTIFY               //   # - ,   
    NotifyClient();
# endif
#endif
    BackToNormal();
  }

//  -   
  if (lopsided_score) {
    #if DISASTER_PENDING  // ! "#if"     
    DropEverything();
    #endif                // !     "#endif"
    BackToNormal();
  }

Klassenformatierung


Ordnen Sie die Abschnitte in der folgenden Reihenfolge an: öffentlich , geschützt und privat . Einrückung ist ein Leerzeichen.

Das Grundformat für die Klasse wird unten beschrieben (mit Ausnahme von Kommentaren siehe Kommentar zur Klassenbeschreibung):

class MyClass : public OtherClass {
 public:      //  1 
  MyClass();  //  2-  
  explicit MyClass(int var);
  ~MyClass() {}

  void SomeFunction();
  void SomeFunctionThatDoesNothing() {
  }

  void set_some_var(int var) { some_var_ = var; }
  int some_var() const { return some_var_; }

 private:
  bool SomeInternalFunction();

  int some_var_;
  int some_other_var_;
};

Bemerkungen:

  • Der Name der Basisklasse wird in dieselbe Zeile geschrieben wie der Name der geerbten Klasse (natürlich unter Berücksichtigung der Beschränkung auf 80 Zeichen).
  • Schlüsselwörter: public : , protected,: und private: sollten um ein Leerzeichen eingerückt werden.
  • Vor jedem dieser Schlüsselwörter muss eine Leerzeile stehen (mit Ausnahme der ersten Erwähnung). In kleinen Klassen können auch Leerzeilen weggelassen werden.
  • Fügen Sie nach diesen Schlüsselwörtern keine Leerzeile ein.
  • Der öffentliche Bereich sollte der erste sein, dahinter geschützt und am Ende der private Bereich .
  • Informationen zum Erstellen von Deklarationen finden Sie in jedem dieser Abschnitte unter Deklarationsverfahren.

Konstruktorinitialisierungslisten


Konstruktorinitialisierungslisten können sich in einer Zeile oder in mehreren Zeilen mit 4 Leerzeichen befinden.

Das Folgende sind die richtigen Formate für Initialisierungslisten:

//    
MyClass::MyClass(int var) : some_var_(var) {
  DoSomething();
}

//          ,
//           
MyClass::MyClass(int var)
    : some_var_(var), some_other_var_(var + 1) {
  DoSomething();
}

//     ,     
//     
MyClass::MyClass(int var)
    : some_var_(var),             //  4 
      some_other_var_(var + 1) {  //   
  DoSomething();
}

//     ,       
MyClass::MyClass(int var)
    : some_var_(var) {}

Namespaces formatieren


Der Namespace-Inhalt wird eingerückt.

Der Namespace fügt keine Auffüllung hinzu. Zum Beispiel:

namespace {

void foo() {  // .   
  ...
}

}  // namespace

Nicht in den Namespace einrücken:

namespace {

  // .   ,   
  void foo() {
    ...
  }

}  // namespace

Platzieren Sie beim Deklarieren verschachtelter Namespaces jede Deklaration in einer separaten Zeile.

namespace foo {
namespace bar {

Horizontale Aufteilung


Verwenden Sie gegebenenfalls horizontale Aufschlüsselungen. Fügen Sie niemals Leerzeichen am Ende einer Zeile ein.

Allgemeine Grundsätze


void f(bool b) {  //       
  ...
int i = 0;  //       
//            .
//    ,      
int x[] = { 0 };
int x[] = {0};

//        
class Foo : public Bar {
 public:
  //  inline-  
  //     (  )
  Foo(int b) : Bar(), baz_(b) {}  //    
  void Reset() { baz_ = 0; }  //      
  ...

Das Hinzufügen von Trennzeichen kann die Zusammenführung von Code beeinträchtigen. Deshalb: Fügen Sie dem vorhandenen Code keine Trennzeichen hinzu. Sie können Leerzeichen entfernen, wenn Sie diese Zeile bereits geändert haben. Oder machen Sie es als separate Operation (es ist vorzuziehen, dass niemand mit diesem Code arbeitet).

Zyklen und Bedingungen


if (b) {          //        
} else {          //   else
}
while (test) {}   //       
switch (i) {
for (int i = 0; i < 5; ++i) {
//         .   .
//   ,  
switch ( i ) {
if ( test ) {
for ( int i = 0; i < 5; ++i ) {
//         
//          ,   
for ( ; i < 5 ; ++i) {
  ...

//           
for (auto x : counts) {
  ...
}
switch (i) {
  case 1:         //    case  
    ...
  case 2: break;  //    ,   (   )  

Betreiber


//     
x = 0;

//      ,
//   /   .
//          
v = w * x + y / z;
v = w*x + y/z;
v = w * (x + z);

//       
x = -5;
++x;
if (x && !y)
  ...

Muster und Abgüsse


//       (<  >),
//  <,  >(  
std::vector<std::string> x;
y = static_cast<char*>(x);

//        .       
std::vector<char *> x;

Vertikale Aufteilung


Vertikale Aufteilung minimieren.

Dies ist eher ein Prinzip als eine Regel: Fügen Sie keine Leerzeilen ohne besonderen Bedarf hinzu. Setzen Sie insbesondere nicht mehr als 1-2 Leerzeilen zwischen Funktionen, starten Sie die Funktion nicht mit einer Leerzeile, beenden Sie die Funktion nicht mit einer Leerzeile und versuchen Sie, weniger Leerzeilen zu verwenden. Eine leere Zeile in einem Codeblock sollte wie ein Absatz in einem Roman funktionieren: zwei Ideen visuell trennen.

Das Grundprinzip: Je mehr Code auf einen Bildschirm passt, desto einfacher ist es, die Ausführungsreihenfolge zu verstehen und zu verfolgen. Verwenden Sie die leere Zeichenfolge ausschließlich, um diese Sequenz visuell zu trennen.

Einige hilfreiche Hinweise zu Leerzeilen:

  • Eine leere Zeile am Anfang oder am Ende einer Funktion verbessert die Lesbarkeit nicht.
  • Leere Zeilen in der if-else-Blockchain können die Lesbarkeit verbessern.
  • Eine leere Zeile vor der Kommentarzeile verbessert normalerweise die Lesbarkeit des Codes. Ein neuer Kommentar beinhaltet normalerweise die Vervollständigung eines alten Gedankens und den Beginn einer neuen Idee. Und die leere Zeile deutet deutlich darauf hin.

All Articles