Ich lese einige Vorlesungsunterlagen meines C ++ - Dozenten und er schrieb Folgendes:
- Verwenden Sie Einrückung // OK
- Verlassen Sie sich niemals auf die Priorität des Operators - Verwenden Sie immer Klammern // OK
- Verwenden Sie immer einen {} Block - auch für eine einzelne Zeile // nicht OK , warum ???
- Const-Objekt auf der linken Seite des Vergleichs // OK
- Verwenden Sie unsigned für Variablen, die> = 0 // netter Trick sind
- Setzen Sie den Zeiger nach dem Löschen auf NULL - Doppelter Löschschutz // nicht schlecht
Die 3. Technik ist mir nicht klar: Was würde ich gewinnen, wenn ich eine Zeile in eine setzen würde { ... }
?
Nehmen Sie zum Beispiel diesen seltsamen Code:
int j = 0;
for (int i = 0 ; i < 100 ; ++i)
{
if (i % 2 == 0)
{
j++;
}
}
und ersetzen Sie es durch:
int j = 0;
for (int i = 0 ; i < 100 ; ++i)
if (i % 2 == 0)
j++;
Was ist der Vorteil der 1. Version?
for (unsigned i = 100; i >= 0; --i)
.(i % 2 == 0)
widerspricht (2). Sie verlassen sich auf die Priorität des Operators, und die Bedeutung ist natürlich((i % 2) == 0)
eher als(i % (2 == 0))
. Ich würde Regel 2 als "ein gültiges Gefühl klassifizieren, aber 'immer' ist falsch".Antworten:
Versuchen
i
wir auch zu ändern, wenn wir inkrementierenj
:Ach nein! Aus Python kommend sieht das in Ordnung aus, ist es aber nicht, da es gleichbedeutend ist mit:
Natürlich ist dies ein dummer Fehler, den aber selbst ein erfahrener Programmierer machen könnte.
Ein weiterer sehr guter Grund ist in der Antwort von ta.speot.is aufgeführt .
Ein dritter, an den ich denken kann, ist verschachtelt
if
:Angenommen, Sie möchten jetzt,
doSomethingElse()
wanncond1
nicht erfüllt wird (neue Funktion). Damit:das ist offensichtlich falsch, da die
else
mit dem inneren assoziiertif
.Bearbeiten: Da dies einige Aufmerksamkeit erhält, werde ich meine Ansicht klarstellen. Die Frage, die ich beantwortete, ist:
Was ich beschrieben habe. Es gibt einige Vorteile. Aber IMO, "immer" Regeln gelten nicht immer. Also unterstütze ich nicht ganz
Ich sage nicht, immer einen
{}
Block zu verwenden. Wenn es eine einfache Bedingung und ein Verhalten ist, tun Sie es nicht. Wenn Sie den Verdacht haben, dass später jemand hereinkommt und Ihren Code ändert, um Funktionen hinzuzufügen, tun Sie dies.quelle
i++
zuvor hinzufügenj++
, sind beide Variablen bei ihrer Verwendung weiterhin im Gültigkeitsbereich.i++;
auf eine Weise einrücken, die sofort zeigt, dass er nicht Teil der Schleife ist. (In der Vergangenheit war dies möglicherweise ein vernünftiges Argument, und ich habe solche Probleme gesehen. Vor ungefähr 20 Jahren. Nicht seitdem.)Es ist sehr leicht versehentlich Change Control-Flow mit Kommentaren , wenn Sie nicht verwenden ,
{
und}
. Zum Beispiel:Wenn Sie
do_something_else()
mit einem einzeiligen Kommentar auskommentieren, erhalten Sie Folgendes:Es wird kompiliert, aber
must_always_do_this()
nicht immer aufgerufen.Wir hatten dieses Problem in unserer Codebasis, in der jemand einige Funktionen vor der Veröffentlichung sehr schnell deaktiviert hatte. Zum Glück haben wir es bei der Codeüberprüfung festgestellt.
quelle
must_always_do_this();
das ausgeführt wird, wenn Sie // do_something_else () kommentieren.if(debug) \n //print(info);
. Grundsätzlich nahm eine ganze Bibliothek heraus.Fortunately we caught it in code review.
Autsch! Das klingt so falsch.Fortunately we caught it in unit tests.
wäre viel besser!Ich habe meine Zweifel an der Kompetenz des Dozenten. In Anbetracht seiner Punkte:
(b*b) - ((4*a)*c)
? Einige Präzedenzfälle sind offensichtlich (oder sollten es sein), und die zusätzlichen Klammern tragen nur zur Verwirrung bei. (Andererseits sollten Sie die Klammern in weniger offensichtlichen Fällen verwenden, selbst wenn Sie wissen, dass sie nicht benötigt werden.){
ist nicht so sichtbar, daher ist es am besten anzunehmen, dass sie immer da ist. Im zweiten Fall habe ich (und die meisten Leute, mit denen ich gearbeitet habe) jedoch kein Problem damit, die geschweiften Klammern für eine einzelne Aussage wegzulassen. (Vorausgesetzt natürlich, dass die Einrückung systematisch ist und Sie diesen Stil konsequent verwenden. (Und viele sehr gute Programmierer, die sehr lesbaren Code schreiben, lassen die geschweiften Klammern weg, selbst wenn sie auf die erste Weise formatiert werden.)if ( NULL == ptr )
sind hässlich genug, um die Lesbarkeit zu beeinträchtigen. Schreiben Sie die Vergleiche intuitiv. (Was in vielen Fällen zur Konstanten rechts führt.) Seine 4 ist ein schlechter Rat; Alles, was den Code unnatürlich macht, macht ihn weniger lesbar.int
als für Sonderfälle reserviert. Für erfahrene C- und C ++ - Programmierer ist die Verwendung vonunsigned
Signalbitoperatoren. C ++ hat keinen echten Kardinaltyp (oder einen anderen effektiven Unterbereichstyp).unsigned
funktioniert aufgrund der Promotion-Regeln nicht für numerische Werte. Numerische Werte, bei denen keine arithmetischen Operationen sinnvoll wären, wie Seriennummern, könnten vermutlich seinunsigned
. Ich würde jedoch dagegen argumentieren, weil es die falsche Nachricht sendet: Bitweise Operationen machen auch keinen Sinn. Die Grundregel ist, dass integrale Typen sindint
, es sei denn, es gibt einen signifikanten Grund für die Verwendung eines anderen Typs.delete this;
ist oft der häufigste Fall (und Sie können nicht eingestelltthis
zuNULL
), und ansonsten die meistendelete
sind in Destruktoren, so dass Sie nicht den Zeiger später sowieso zugreifen können. Wenn Sie esNULL
so einstellen, wird nichts gegen andere herumschwebende Zeiger unternommen. Wenn Sie den Zeiger systematisch auf setzen,NULL
entsteht ein falsches Sicherheitsgefühl, und Sie kaufen nichts.Sehen Sie sich den Code in einer der typischen Referenzen an. Stroustrup verstößt gegen jede Regel, die Sie angegeben haben, mit Ausnahme der ersten.
Ich würde vorschlagen, dass Sie einen anderen Dozenten finden. Einer, der tatsächlich weiß, wovon er spricht.
quelle
delete this
, ist es häufiger als ich gesehen habe? Ich neige nicht dazu zu denken, dass das Setzen eines Zeigers auf NULL nach der Verwendung so schlecht ist, außer YMMV. Vielleicht bin ich es nur, aber die meisten seiner Richtlinien scheinen nicht so schlecht zu sein.if (ptr = NULL)
sei denn, Sie schreiben es alsif ((ptr = NULL))
. Ich muss James Kanze zustimmen, dass die Hässlichkeit,NULL
zuerst zu haben, es definitiv zu einem NEIN für mich macht.unsigned
ein Bestreben des Programmierers, dass die Variable nur positive Zahlen darstellen soll. Das Mischen mit signierten Nummern führt normalerweise zu einer Compiler-Warnung, die wahrscheinlich vom Dozenten beabsichtigt wurde.size_t
jemand?Alle anderen Antworten verteidigen die Regel 3 Ihres Dozenten.
Lassen Sie mich sagen, dass ich Ihnen zustimme: Die Regel ist überflüssig und ich würde sie nicht empfehlen. Es ist wahr, dass es theoretisch Fehler verhindert, wenn Sie immer geschweifte Klammern hinzufügen. Andererseits bin ich im wirklichen Leben noch nie auf dieses Problem gestoßen : Im Gegensatz zu anderen Antworten habe ich nicht einmal vergessen, die geschweiften Klammern hinzuzufügen, sobald sie notwendig wurden. Wenn Sie die richtige Einrückung verwenden, wird sofort klar, dass Sie geschweifte Klammern hinzufügen müssen, sobald mehr als eine Anweisung eingerückt ist.
Die Antwort von „Komponente 10“ hebt tatsächlich den einzig denkbaren Fall hervor, in dem dies wirklich zu einem Fehler führen könnte. Andererseits erfordert das Ersetzen von Code durch reguläre Ausdrücke ohnehin immer enorme Sorgfalt.
Schauen wir uns nun die andere Seite der Medaille an: Gibt es einen Nachteil , wenn Sie immer geschweifte Klammern verwenden? Die anderen Antworten ignorieren diesen Punkt einfach. Aber das gibt es einen Nachteil: Es nimmt viel vertikalen Bildschirmplatz ein, was wiederum dazu führen kann, dass Ihr Code nicht mehr lesbar ist, da Sie mehr als nötig scrollen müssen.
Betrachten Sie eine Funktion mit vielen Schutzklauseln am Anfang (und ja, das Folgende ist schlechter C ++ - Code, aber in anderen Sprachen wäre dies eine recht häufige Situation):
Dies ist ein schrecklicher Code, und ich behaupte nachdrücklich, dass Folgendes weitaus besser lesbar ist:
In ähnlicher Weise profitieren kurze verschachtelte Schleifen davon, dass die geschweiften Klammern weggelassen werden:
Vergleichen mit:
Der erste Code ist kurz; Der zweite Code ist aufgebläht.
Und ja, dies kann bis zu einem gewissen Grad gemildert werden , indem die Öffnungsklammer auf die vorherige Zeile gesetzt wird. Aber das würde immer noch noch weniger lesbar als der Code ohne geschweifte Klammern.
Kurz gesagt: Schreiben Sie keinen unnötigen Code, der Platz auf dem Bildschirm beansprucht.
quelle
if (a == nullptr) { throw null_ptr_error("a"); }
als eine Zeile.Die Codebasis, an der ich arbeite, ist mit Code von Personen verstreut, die eine pathologische Abneigung gegen Zahnspangen haben, und für die Personen, die später kommen, kann dies die Wartbarkeit wirklich verbessern.
Das häufigste problematische Beispiel, auf das ich gestoßen bin, ist folgendes:
Wenn ich also vorbeikomme und eine damalige Aussage hinzufügen möchte, kann ich leicht damit enden, wenn ich nicht aufpasse:
Da es dauert ~ 1 Sekunde zu Klammern hinzuzufügen und können Sie mindestens ein paar Minuten verwirrt speichern debuggen, warum Sie überhaupt nicht gehen mit der reduzierten-Mehrdeutigkeit Option? Scheint mir eine falsche Wirtschaft zu sein.
quelle
if(really long...editor){ do_foo;}
Sie diesen Fall vermeiden können? Das Problem scheint immer noch dasselbe zu sein. Ich persönlich bevorzuge es, Klammern zu vermeiden, wenn dies nicht erforderlich ist. Dies hat jedoch nichts mit der zum Schreiben erforderlichen Zeit zu tun, sondern mit der verringerten Lesbarkeit aufgrund der zwei zusätzlichen Zeilen im Code.Mein 2c:
Offensichtlich
Ich würde die Wörter "nie und" immer "nicht verwenden, aber im Allgemeinen sehe ich diese Regel als nützlich an. In einigen Sprachen (Lisp, Smalltalk) ist dies kein Problem.
Ich mache das nie und hatte nie ein einziges Problem, aber ich kann sehen, wie gut es für Studenten sein kann, insb. wenn sie vorher Python studiert haben.
Yoda Bedingungen? Nein, bitte. Es schadet der Lesbarkeit. Verwenden Sie einfach die maximale Warnstufe, wenn Sie Ihren Code kompilieren.
OK. Komischerweise habe ich gehört, dass Stroustrup anderer Meinung ist.
Schlechter Rat! Haben Sie niemals einen Zeiger, der auf ein gelöschtes oder nicht vorhandenes Objekt zeigt.
quelle
unsigned
ist kaputt" zu vervollständigen , besteht eines der Probleme darin, dass C ++ beim Vergleich von signierten und nicht signierten Typen ähnlicher Größe vor dem Vergleich in den nicht signierten Typ konvertiert . Was zu einer Wertänderung führt. Das Konvertieren in das Signierte wäre nicht unbedingt viel besser. Der Vergleich sollte wirklich so stattfinden, als ob beide Werte in einen größeren Typ konvertiert würden, der alle Werte in beiden Typen darstellen könnte.unsigned
. Ich bin sicher, er hat kein Problem damitexp(double)
, einen Wert zurückzugeben, der größer ist alsMAX_INT
:-). Aber noch einmal, das eigentliche Problem sind implizite Konvertierungen.int i = exp( 1e6 );
ist vollkommen gültiges C ++. Stroustrup schlug tatsächlich vor, verlustbehaftete implizite Conversions an einem Punkt zu verwerfen, aber das Komitee war nicht interessiert. (Eine interessante Frage: würdeunsigned
->int
als verlustbehaftet angesehen werden. Ich würde sowohlunsigned
->int
als auchint
-> alsunsigned
verlustbehaftet betrachten. Das würde einen großenunsigned
es ist intuitiver und leicht verständlich. Es macht die Absicht klar.
Und es stellt sicher, dass der Code nicht beschädigt wird, wenn ein neuer Benutzer den Code unwissentlich verpasst
{
,}
während eine neue Code-Anweisung hinzugefügt wird.quelle
Makes the intent clear
+1, dies ist wahrscheinlich der prägnanteste und genaueste Grund.Um die oben genannten sehr vernünftigen Vorschläge zu ergänzen, war ein Beispiel, das ich beim Umgestalten eines Codes gefunden habe, bei dem dies kritisch wird, wie folgt: Ich habe eine sehr große Codebasis geändert, um von einer API zu einer anderen zu wechseln. Die erste API hatte einen Aufruf zum Festlegen der Unternehmens-ID wie folgt:
Für den Ersatz waren zwei Anrufe erforderlich:
Ich habe mich daran gemacht, dies mit regulären Ausdrücken zu ändern, was sehr erfolgreich war. Wir haben den Code auch durch astyle weitergegeben , was ihn wirklich sehr viel lesbarer machte. Während des Überprüfungsprozesses stellte ich dann fest, dass sich dies unter bestimmten Bedingungen änderte:
Dazu:
Das ist eindeutig nicht das, was erforderlich war. Ich musste zum Anfang zurückkehren und dies erneut tun, indem ich den Ersatz als vollständig innerhalb eines Blocks behandelte und dann manuell alles änderte, was doof aussah (zumindest wäre es nicht falsch.)
Ich stelle fest, dass Astyle jetzt die Option hat
--add-brackets
, mit der Sie Klammern hinzufügen können, in denen es keine gibt, und ich empfehle dies dringend, wenn Sie sich jemals in derselben Position wie ich befinden.quelle
#define FOO() func1(); \ func2();
(mit einem Zeilenumbruch nach dem Backslash). Gleiches gilt für das Suchen und Ersetzen. Trotzdem habe ich gesehen, dass "Verwenden Sie immer geschweifte Klammern" als Stilregel weiterentwickelt wurde, gerade weil Sie dadurch nicht alle Makros mit mehreren Anweisungen einschließen müssendo .. while(0)
. Aber ich bin anderer Meinung.inline
), sollten Sie wahrscheinlich darauf abzielen, dass sie so ähnlich wie möglich funktionieren, unddo { ... } while(0)
bei Bedarf den Trick verwenden (und viele zusätzliche Klammern. Aber das würde immer noch nicht Ich kann Sie nicht davon abhalten, überall Zahnspangen zu verwenden, wenn dies der Hausstil ist. (FWIW: Ich habe an Orten mit unterschiedlichen Hausstilen gearbeitet und alle hier diskutierten Stile abgedeckt. Ich habe nie festgestellt, dass eines ein ernstes Problem darstellt.)Ich benutze
{}
überall, außer in einigen Fällen, in denen es offensichtlich ist. Eine einzelne Zeile ist einer der Fälle:Es kann Ihnen weh tun, wenn Sie vor der Rückkehr eine Methode hinzufügen. Einrückung zeigt an, dass return zurückgegeben wird, wenn die Bedingung erfüllt ist, aber immer zurückgegeben wird.
Ein anderes Beispiel in C # mit der Verwendung von statment
das ist äquivalent zu
quelle
using
Sie einfach Kommas in der Anweisung und Sie müssen nicht :)using
).Das relevanteste Beispiel, an das ich denken kann:
Mit welchem
if
wird daselse
gepaart? Einrückung impliziert, dass das Äußere dasif
bekommtelse
, aber so wird es der Compiler eigentlich nicht sehen; das Innereif
wird das bekommenelse
, und das Äußereif
nicht. Sie müssten das wissen (oder sehen, dass es sich im Debugging-Modus so verhält), um durch Inspektion herauszufinden, warum dieser Code möglicherweise Ihre Erwartungen nicht erfüllt. Es wird verwirrender, wenn Sie Python kennen. In diesem Fall wissen Sie, dass der Einzug Codeblöcke definiert, sodass Sie erwarten würden, dass er gemäß dem Einzug ausgewertet wird. C # gibt jedoch keinen fliegenden Flip über Leerzeichen.Nun, das heißt, ich stimme dieser Regel "Immer Klammern verwenden" auf den ersten Blick nicht besonders zu. Es macht Code sehr vertikal verrauscht und verringert die Fähigkeit, ihn schnell durchzulesen. Wenn die Aussage lautet:
... dann sollte es einfach so geschrieben werden. Die Aussage "Klammern immer verwenden" klingt wie "mathematische Operationen immer mit Klammern umgeben". Das würde die sehr einfache Aussage
a * b + c / d
in((a * b) + (c / d))
die Möglichkeit verwandeln, einen Close-Paren (den Fluch vieler Codierer) zu verpassen, und wofür? Die Reihenfolge der Operationen ist bekannt und wird gut durchgesetzt, sodass die Klammern redundant sind. Sie würden nur Klammern verwenden, um eine andere Reihenfolge von Operationen zu erzwingen, als normalerweise angewendet wird:a * (b+c) / d
zum Beispiel. Blockklammern sind ähnlich; Verwenden Sie sie, um zu definieren, was Sie in Fällen tun möchten, in denen es vom Standard abweicht und nicht "offensichtlich" ist (subjektiv, aber normalerweise ziemlich vernünftig).quelle
else
mit der erstenif
anstelle der zweiten zu koppeln. Bitte entfernen Sie die Ablehnung.Beim Durchsehen der Antworten hat niemand ausdrücklich angegeben, welche Art von Praxis ich mir angewöhnt habe, und die Geschichte Ihres Codes erzählt:
Wird:
Das setzen
j++
in die gleiche Zeile wie das if, um anderen zu signalisieren: "Ich möchte nur, dass dieser Block jemals erhöht wirdj
" . Natürlich lohnt sich dies nur, wenn die Linie so einfach wie möglich ist, weil hier ein Haltepunkt als Peri gesetzt wird erwähnt, wird nicht sehr nützlich sein.Tatsächlich bin ich gerade auf einen Teil der Twitter Storm-API gestoßen, die diese Art von Code in Java enthält. Hier ist das relevante Snippet aus dem Ausführungscode auf Seite 43 dieser Diashow :
Der for-Schleifenblock enthält zwei Dinge, daher würde ich diesen Code nicht einbinden. Dh niemals :
Es ist schrecklich und ich weiß nicht einmal, ob es funktioniert (wie beabsichtigt); Tu das nicht . Neue Zeilen und geschweifte Klammern helfen dabei, separate, aber verwandte Codeteile zu unterscheiden, genau wie ein Komma oder ein Semikolon in der Prosa. Der obige Block ist genauso schlecht wie ein wirklich langer Satz mit ein paar Klauseln und einigen anderen Aussagen, die niemals brechen oder pausieren, um einzelne Teile zu unterscheiden.
Wenn Sie wirklich an eine andere Person telegrafieren möchten, verwenden Sie einen ternären Operator oder
?:
Formular:Aber das ist fast Code-Golf, und ich denke nicht, dass es eine großartige Übung ist (mir ist nicht klar, ob ich das j ++ auf eine Seite von setzen soll
:
oder nicht). NB Ich habe noch keinen ternären Operator in C ++ ausgeführt. Ich weiß nicht, ob dies funktioniert, aber es existiert .Zusamenfassend:
Stellen Sie sich vor, wie Ihr Leser (dh die Person, die den Code verwaltet) Ihre Geschichte (Code) interpretiert. Machen Sie es ihnen so klar wie möglich. Wenn Sie wissen, dass der Anfänger / Student dies beibehält, lassen Sie vielleicht sogar so viele
{}
wie möglich übrig, damit sie nicht verwirrt werden.quelle
for
Schleife in eine einzelne Zeile setzen. Warum sollte das nicht funktionieren? Es funktioniert aus dem gleichen Grund, aus dem Sie die geschweiften Klammern weglassen können. newline ist in C ++ einfach nicht von Bedeutung. (3) Ihr Beispiel für einen bedingten Operator ist nicht nur schrecklich, sondern auch ungültig in C ++.Denn wenn Sie zwei Aussagen ohne haben
{}
, ist es leicht, ein Problem zu übersehen. Nehmen wir an, dass der Code so aussieht.Es sieht gut aus. Das Problem damit ist wirklich leicht zu übersehen, besonders wenn die Funktion, die den Code enthält, viel größer ist. Das Problem ist, dass
goto fail
es bedingungslos ausgeführt wird. Sie können sich leicht vorstellen, wie frustrierend dies ist (Sie fragen sich, warum der letztehash_update
immer fehlschlägt, schließlich sieht alles gut aushash_update
Funktion gut aus).Das bedeutet jedoch nicht, dass ich
{}
überall etwas hinzufügen möchte (meiner Meinung nach{}
ist es ärgerlich , überall zu sehen). Es kann zwar Probleme verursachen, hat es aber nie für meine eigenen Projekte getan, da mein persönlicher Codierungsstil Bedingungen verbietet, ohne{}
dass sie nicht in derselben Zeile stehen (ja, ich stimme zu, dass mein Codierungsstil unkonventionell ist, aber ich mag es und ich Verwenden Sie den Codestil des Projekts, wenn Sie zu anderen Projekten beitragen. Dies macht den folgenden Code in Ordnung.Aber nicht der folgende.
quelle
Es macht Ihren Code besser lesbar, indem es den Umfang Ihrer Schleifen und bedingten Blöcke klar definiert. Es erspart Ihnen auch versehentliche Fehler.
quelle
wrt 6: Es ist sicherer, weil das Löschen eines Nullzeigers ein No-Op ist. Wenn Sie diesen Pfad also versehentlich zweimal durchlaufen, wird die Speicherbeschädigung nicht dazu führen, dass Speicher freigegeben wird, der entweder frei ist oder einem anderen zugewiesen wurde.
Dies ist das größte Problem bei statischen Dateibereichsobjekten und Singletons, deren Lebensdauer nicht sehr klar ist und von denen bekannt ist, dass sie nach ihrer Zerstörung neu erstellt werden.
In den meisten Fällen können Sie dies mithilfe von auto_ptrs vermeiden
quelle
NULL
nach dem Löschen festlegen würden . WennNULL
der Zeiger unter diesen Umständen einen korrekten Wert hat, z. B. zeigt der Zeiger auf einen zwischengespeicherten Wert undNULL
zeigt einen ungültigen Cache an. Wenn Sie jedoch eine Einstellung sehen Als Zeiger aufNULL
die letzte Zeile in einem Destruktor fragen Sie sich, ob er C ++ kennt.)Ich mag Luchians akzeptierte Antwort, tatsächlich habe ich auf die harte Tour gelernt, dass er Recht hat, deshalb verwende ich immer geschweifte Klammern, auch für einzeilige Blöcke. Ich persönlich mache jedoch eine Ausnahme, wenn ich einen Filter schreibe, wie Sie es in Ihrem Beispiel sind. Diese:
sieht für mich überladen aus. Es trennt die for-Schleife und die if-Anweisung in separate Aktionen, wenn Ihre Absicht wirklich eine einzelne Aktion ist: Alle durch 2 teilbaren Ganzzahlen zu zählen. In einer ausdrucksstärkeren Sprache könnte dies wie folgt geschrieben werden:
In Sprachen ohne Abschluss kann der Filter nicht in einer einzelnen Anweisung ausgedrückt werden, sondern muss eine for-Schleife gefolgt von einer if-Anweisung sein. Es ist jedoch immer noch eine Aktion im Kopf des Programmierers, und ich glaube, dass dies im Code wie folgt widergespiegelt werden sollte:
quelle
for (int i = 0; i < 100; i += 2);
, um das Argument der Einrückung fortzusetzen ;-) Wir könnten wahrscheinlich einen eigenen Kampf haben, wie "am besten" wir die Logik "für jedeni
in einem bestimmten Bereich mit einer bestimmten Eigenschaft" ausdrücken können. in C ++ ohne Schleife, unter Verwendung einer Albtraumkombination von Standardalgorithmenfilter_iterator
und / odercounting_iterator
.i
in einem bestimmten Bereich mit einer bestimmten Eigenschaft" abstrahiert . Es ist nur so, dass die Leute bei SO normalerweise die eigentliche Frage sehr schnell ignorieren, um einen völlig anderen Ansatz für das gegebene Beispiel zu finden. Aber das Einrücken ist wichtig , also tun wir es nicht ;-)Eine Möglichkeit, um die oben beschriebenen Fehler zu vermeiden, besteht darin, anzugeben, was passieren soll, wenn Sie keine geschweiften Klammern verwenden. Es macht es viel schwieriger, die Fehler nicht zu bemerken, wenn Sie versuchen, den Code zu ändern.
quelle
else
nicht mit einem verknüpft istif
.Wenn Sie ein Compiler sind, macht es keinen Unterschied. Beide sind gleich.
Für Programmierer ist der erste jedoch klarer, leicht zu lesen und weniger fehleranfällig.
quelle
{
davon, dass man auf eigene Faust öffnet .Ein weiteres Beispiel für das Hinzufügen von geschweiften Klammern. Einmal habe ich nach einem Fehler gesucht und einen solchen Code gefunden:
Wenn Sie die Methode Zeile für Zeile lesen, werden Sie feststellen, dass die Methode eine Bedingung enthält, die zurückgegeben wird, wenn sie nicht wahr ist. Aber tatsächlich sieht es aus wie 100 andere einfache Ereignishandler, die einige Variablen basierend auf bestimmten Bedingungen festlegen. Und eines Tages kommt der Fast Coder und fügt am Ende der Methode eine zusätzliche Anweisung zur Variableneinstellung hinzu:
Infolgedessen wird SetAnotherVariableUnconditionnaly ausgeführt, wenn SomeConditionIsMet (), aber der schnelle Typ hat es nicht bemerkt, da alle Zeilen fast gleich groß sind und selbst wenn die Rückgabebedingung vertikal eingerückt ist, ist sie nicht so auffällig.
Wenn die bedingte Rückgabe wie folgt formatiert ist:
es ist sehr auffällig und der Fast Coder wird es auf einen Blick finden.
quelle
return
Anweisung im Hauptteil einer Funktion zu erkennen, bevor Sie etwas hinzufügen, sollten Sie den schnellen Codierer nicht in die Nähe Ihres Codes bringen lassen. Sie werden einen solchen Kerl nicht davon abhalten, Ihren Code zu durchforsten, indem Sie geschweifte Klammern einfügen.Ich halte den ersten für klar und dann für den zweiten. Es gibt das Gefühl, Anweisungen zu schließen, mit wenig Code ist in Ordnung, wenn Code komplex wird,
{...}
hilft viel, selbst wenn esendif
oder istbegin...end
quelle
Setzen Sie den Zeiger am besten auf NULL, wenn Sie damit fertig sind.
Hier ist ein Beispiel warum:
Klasse A macht Folgendes:
Klasse B macht Folgendes
Zu diesem Zeitpunkt haben sowohl Klasse A als auch Klasse B Zeiger, die auf denselben Speicherblock zeigen, was Klasse A betrifft, existiert dieser Speicherblock nicht, weil er damit fertig ist.
Betrachten Sie das folgende Problem:
Was ist, wenn in Klasse A ein logischer Fehler aufgetreten ist, der dazu geführt hat, dass in den Speicher geschrieben wurde, der jetzt zur Klasse B gehört?
In diesem speziellen Fall wird kein Fehler bei einer fehlerhaften Zugriffsausnahme angezeigt, da die Speicheradresse zulässig ist, während Klasse A jetzt effektiv Daten der Klasse B beschädigt.
Klasse B kann schließlich abstürzen, wenn unerwartete Werte auftreten, und wenn es abstürzt, werden Sie wahrscheinlich ziemlich lange Zeit damit verbringen, diesen Fehler in Klasse B zu suchen, wenn das Problem in Klasse A liegt.
Wenn Sie den gelöschten Speicherzeiger auf NULL gesetzt hätten, hätten Sie einen Ausnahmefehler erhalten, sobald Logikfehler in Klasse A versucht hätten, in den NULL-Zeiger zu schreiben.
Wenn Sie sich Sorgen über den Logikfehler beim doppelten Löschen machen, wenn die Zeiger zum zweiten Mal NULL sind, fügen Sie hierfür assert hinzu.
Außerdem: Wenn Sie abstimmen wollen, erklären Sie dies bitte.
quelle
Immer geschweifte Klammern zu haben, ist eine sehr einfache und robuste Regel. Der Code kann jedoch unelegant aussehen, wenn viele Klammern vorhanden sind. Wenn die Regeln das Weglassen von geschweiften Klammern zulassen, sollten detailliertere Stilregeln und ausgefeiltere Werkzeuge vorhanden sein. Andernfalls kann es leicht zu chaotischem und verwirrendem (nicht elegantem) Code kommen. Daher ist es wahrscheinlich erfolglos, eine einzelne Stilregel getrennt von den übrigen verwendeten Stilrichtlinien und Werkzeugen zu betrachten. Ich werde nur einige wichtige Details zu dieser Regel Nr. 3 einbringen, die in anderen Antworten noch nicht einmal erwähnt wurden.
Das erste interessante Detail ist, dass die meisten Befürworter dieser Regel zustimmen, sie im Falle von zu verletzen
else
. Mit anderen Worten, sie verlangen bei der Überprüfung eines solchen Codes nicht:Wenn sie es sehen, können sie stattdessen sogar vorschlagen, es so zu schreiben:
Dies verstößt technisch gegen diese Regel, da zwischen
else
und keine geschweiften Klammern stehenif
. Eine solche Dualität der Regel tritt auf, wenn versucht wird, sie mit einem sinnlosen Werkzeug automatisch auf die Codebasis anzuwenden. In der Tat, warum streiten, lassen Sie einfach ein Werkzeug, um Stil automatisch anzuwenden.Das zweite Detail (das auch von Befürwortern dieser Regel oft vergessen wird) ist, dass die Fehler, die auftreten können, niemals nur auf Verstöße gegen diese Regel Nr. 3 zurückzuführen sind. Tatsächlich beinhalten diese fast immer auch Verstöße gegen Regel Nr. 1 (mit denen niemand argumentiert). Auch aus Sicht der automatischen Tools ist es nicht schwer, ein Tool zu erstellen, das sich sofort beschwert, wenn Regel 1 verletzt wird, sodass die meisten Fehler rechtzeitig erkannt werden können.
Das dritte Detail (das von Gegnern dieser Regel oft vergessen wird) ist die verwirrende Natur einer leeren Aussage, die durch ein einzelnes Semikolon dargestellt wird. Die meisten Entwickler mit etwas Erfahrung wurden früher oder später durch ein alleiniges falsch platziertes Semikolon oder durch eine leere Anweisung, die mit einem einzigen Semikolon geschrieben wurde, verwirrt. Zwei geschweifte Klammern anstelle eines einzelnen Semikolons sind optisch viel einfacher zu erkennen.
quelle
Ich muss zugeben, dass dies nicht immer
{}
für eine einzelne Zeile verwendet wird, aber es ist eine gute Praxis.Nehmen wir an, Sie schreiben einen Code ohne Klammern, der so aussieht:
für (int i = 0; i <100; ++ i) für (int j = 0; j <100; ++ j) DoSingleStuff ();
Und nach einiger Zeit möchten Sie in einer
j
Schleife einige andere Dinge hinzufügen, und Sie tun dies einfach durch Ausrichten und vergessen, Klammern hinzuzufügen.Speicherfreigabe ist schneller. Nehmen wir an, Sie haben einen großen Umfang und erstellen große Arrays im Inneren (ohne
new
dass sie im Stapel sind). Diese Arrays werden unmittelbar nach dem Verlassen des Bereichs aus dem Speicher entfernt. Es ist jedoch möglich, dass Sie dieses Array an einem Ort verwenden und es für eine Weile im Stapel liegt und eine Art Müll ist. Da ein Stapel eine begrenzte und recht kleine Größe hat, ist es möglich, die Stapelgröße zu überschreiten. In einigen Fällen ist es daher besser zu schreiben{}
, um dies zu verhindern. HINWEIS Dies gilt nicht für eine einzelne Leitung, sondern für solche Situationen:if (...) {// SomeStuff ... {// wir haben kein if, while usw. // SomeOtherStuff} // SomeMoreStuff}
Die dritte Art der Verwendung ist ähnlich wie bei der zweiten. Es geht nur nicht darum, den Stapel sauberer zu machen, sondern einige Funktionen zu öffnen . Wenn Sie
mutex
in langen Funktionen arbeiten, ist es normalerweise besser, kurz vor dem Zugriff auf Daten und kurz nach dem Lesen / Schreiben zu sperren und zu entsperren. HINWEIS Diese Methode wird verwendet, wenn Sie eigeneclass
oderstruct
mitconstructor
unddestructor
zum Sperren des Speichers haben.Was ist mehr:
if (...) if (...) SomeStuff (); sonst SomeOtherStuff (); // geht zum zweiten wenn, aber die Zuordnung zeigt, dass es zuerst eingeschaltet ist ...
Alles in allem kann ich nicht sagen, was der beste Weg ist, immer
{}
für eine einzelne Zeile zu verwenden, aber es ist nichts Schlechtes, das zu tun.WICHTIGE BEARBEITUNG Wenn Sie das Kompilieren von Code-Klammern für eine einzelne Zeile schreiben, geschieht nichts, aber wenn Ihr Code interpretiert wird, verlangsamt sich der Code geringfügig. Kaum.
quelle
Es gibt eine Reihe von Möglichkeiten, Steueranweisungen zu schreiben. Bestimmte Kombinationen von ihnen können nebeneinander existieren, ohne die Lesbarkeit zu beeinträchtigen. Andere Kombinationen verursachen jedoch Probleme. Der Style
wird bequem mit einigen anderen Arten des Schreibens von Kontrollanweisungen koexistieren, aber nicht so gut mit anderen. Wenn mehrzeilige gesteuerte Anweisungen wie folgt geschrieben werden:
dann ist es visuell offensichtlich, welche
if
Anweisungen eine einzelne Zeile und welche mehrere Zeilen steuern. Wenn jedoch mehrzeiligeif
Anweisungen wie folgt geschrieben werden:Dann ist die Wahrscheinlichkeit, dass jemand versucht,
if
Konstrukte mit einer einzelnen Anweisung zu erweitern, ohne die erforderlichen Klammern hinzuzufügen, viel höher.Die Einzelanweisung in der nächsten Zeile
if
kann auch problematisch sein, wenn die Codebasis das Formular in erheblichem Maße verwendetMeine eigene Präferenz ist, dass die Anweisung in einer eigenen Zeile im Allgemeinen die Lesbarkeit verbessert, außer in Fällen, in denen es viele
if
Anweisungen mit ähnlichen Steuerblöcken gibt, zIn diesem Fall werde ich solchen Gruppen von
if
Anweisungen im Allgemeinen eine Leerzeile voranstellen und folgen , um sie visuell von anderem Code zu trennen. Wenn Sie eine Reihe von Anweisungen haben, die alle mitif
demselben Einzug beginnen, erhalten Sie einen klaren visuellen Hinweis darauf, dass etwas Ungewöhnliches vorliegt.quelle