In C und C ++ sehe ich oft die folgende Konvention:
some_type val;
val = something;
some_type *ptr = NULL;
ptr = &something_else;
Anstatt von
some_type val = something;
some_type *ptr = &something_else;
Ich nahm anfangs an, dass dies eine Gewohnheit war, die von den Tagen übrig geblieben war, als Sie alle lokalen Variablen oben im Gültigkeitsbereich deklarieren mussten. Aber ich habe gelernt, die Gewohnheiten von erfahrenen Entwicklern nicht so schnell zu verwerfen. Gibt es also einen guten Grund, in einer Zeile zu deklarieren und danach zuzuweisen?
Antworten:
C
In C89 alle Erklärungen sein mußten zu Beginn eines Bereichs sein (
{ ... }
), aber diese Forderung wurde schnell fallen gelassen (zunächst mit Compiler - Erweiterungen und später mit dem Standard).C ++
Diese Beispiele sind nicht gleich.
some_type val = something;
ruft den Kopierkonstruktor auf, währendval = something;
der Standardkonstruktor und dann dieoperator=
Funktion aufgerufen werden. Dieser Unterschied ist oft kritisch.Gewohnheiten
Einige Leute deklarieren lieber zuerst Variablen und definieren sie später, falls sie ihren Code später mit den Deklarationen an einer Stelle und der Definition an einer anderen neu formatieren.
In Bezug auf die Zeiger haben einige Leute die Gewohnheit, jeden Zeiger auf
NULL
oder zu initialisierennullptr
, unabhängig davon, was sie mit diesem Zeiger tun.quelle
some_type
Konstruktorsomething
als einziges Argument. Dies ist ein sehr interessanter und ungewöhnlicher Randfall in C ++ ... es bedeutet, dass eine Vermutung über die semantische Bedeutung dieser Operationen besteht.Sie haben Ihre Frage C und C ++ gleichzeitig markiert, während sich die Antwort in diesen Sprachen erheblich unterscheidet.
Erstens ist der Wortlaut des Titels Ihrer Frage falsch (oder genauer gesagt, für die Frage selbst irrelevant). In beiden Beispielen wird die Variable gleichzeitig in einer Zeile deklariert und definiert . Der Unterschied zwischen Ihren Beispielen besteht darin, dass in der ersten Variable die Variablen entweder nicht initialisiert oder mit einem Dummy-Wert initialisiert werden und dieser später ein aussagekräftiger Wert zugewiesen wird. Im zweiten Beispiel werden die Variablen sofort initialisiert .
Zweitens sind diese beiden Konstrukte in C ++ semantisch verschieden, wie @nightcracker in seiner Antwort feststellte. Der erste basiert auf der Initialisierung, der zweite auf der Zuweisung. In C ++ sind diese Operationen überladbar und können daher möglicherweise zu unterschiedlichen Ergebnissen führen (obwohl es keine gute Idee ist, nicht äquivalente Überladungen von Initialisierung und Zuweisung zu erzeugen).
In der ursprünglichen Standardsprache C (C89 / 90) ist es unzulässig, Variablen in der Mitte des Blocks zu deklarieren. Aus diesem Grund werden Variablen möglicherweise am Anfang des Blocks als nicht initialisiert (oder mit Dummy-Werten initialisiert) deklariert und dann sinnvoll zugewiesen Werte später, wenn diese aussagekräftigen Werte verfügbar werden.
In der Sprache C99 ist es in Ordnung, Variablen in der Mitte des Blocks zu deklarieren (genau wie in C ++). Dies bedeutet, dass der erste Ansatz nur in bestimmten Situationen erforderlich ist, in denen der Initialisierer zum Zeitpunkt der Deklaration nicht bekannt ist. (Dies gilt auch für C ++).
quelle
some_type val;
sofort die Variable . Das habe ich in meiner Antwort gemeint.val
Ich denke, es ist eine alte Gewohnheit, die aus "lokalen Deklarations" -Zeiten übrig geblieben ist. Und deshalb als Antwort auf Ihre Frage: Nein, ich glaube nicht, dass es einen guten Grund gibt. Ich mache es nie selbst.
quelle
Darüber habe ich in meiner Antwort auf eine Frage von Helium3 etwas gesagt .
Grundsätzlich sage ich, es ist eine visuelle Hilfe, um leicht zu sehen, was geändert wird.
und
quelle
Die anderen Antworten sind ziemlich gut. In C gibt es eine Geschichte dazu. In C ++ gibt es den Unterschied zwischen einem Konstruktor und einem Zuweisungsoperator.
Ich bin überrascht, dass niemand den zusätzlichen Punkt erwähnt: Deklarationen von der Verwendung einer Variablen zu trennen, kann manchmal viel besser lesbar sein.
Wenn Sie Code lesen, sind die banaleren Artefakte, wie z. B. die Typen und Namen von Variablen, visuell nicht das, was Sie anspricht. Es sind die Aussagen , an denen Sie normalerweise am meisten interessiert sind, auf die Sie die meiste Zeit starren, und daher besteht die Tendenz, einen Blick auf den Rest zu werfen.
Wenn ich einige Typen, Namen und Zuordnungen auf engstem Raum habe, ist das ein bisschen Informationsüberflutung. Darüber hinaus bedeutet dies, dass in dem Bereich, über den ich normalerweise schaue, etwas Wichtiges vor sich geht.
Es mag etwas kontraproduktiv erscheinen, dies ist jedoch ein Beispiel dafür, wie Sie Ihre Quelle verbessern können, indem Sie mehr vertikalen Platz in Anspruch nehmen. Ich sehe das als eine Art Grund, warum Sie keine überfüllten Zeilen schreiben sollten, die verrückte Mengen an Zeigerarithmetik und -zuweisung in einem engen vertikalen Raum ausführen - nur weil die Sprache Sie mit solchen Dingen davonkommen lässt, heißt das nicht, dass Sie es tun sollten es die ganze Zeit. :-)
quelle
In C war dies die Standardpraxis, da Variablen zu Beginn der Funktion deklariert werden mussten, anders als in C ++, wo sie an einer beliebigen Stelle im Funktionskörper deklariert werden konnten, um danach verwendet zu werden. Zeiger wurden auf 0 oder NULL gesetzt, da nur sichergestellt wurde, dass der Zeiger auf keinen Müll zeigte. Ansonsten gibt es keinen signifikanten Vorteil, den ich mir vorstellen kann, was jeden dazu zwingt.
quelle
Vorteile für die Lokalisierung von Variablendefinitionen und deren sinnvolle Initialisierung:
Wenn Variablen gewohnheitsmäßig einen sinnvollen Wert zugewiesen bekommen, wenn sie zum ersten Mal im Code erscheinen (eine andere Perspektive auf dasselbe: Sie verzögern ihr Erscheinen, bis ein sinnvoller Wert verfügbar ist), besteht keine Chance, dass sie versehentlich mit einem sinnlosen oder nicht initialisierten Wert verwendet werden ( Dies kann leicht passieren, wenn eine Initialisierung aufgrund von bedingten Anweisungen, Kurzschlussauswertung, Ausnahmen usw. versehentlich umgangen wird.)
kann effizienter sein
operator=
kann manchmal weniger effizient sein und ein temporäres Objekt erfordernDas Minimieren des Bereichs von Variablen minimiert wiederum die durchschnittliche Anzahl von Variablen, die gleichzeitig im Bereich sind : dies
manchmal prägnanter, da Sie den Variablennamen in einer Definition nicht wiederholen als in einer anfänglichen sinnvollen Zuweisung
Erforderlich für bestimmte Typen, z. B. Referenzen, und für den Zeitpunkt, zu dem das Objekt erstellt werden soll
const
Argumente zum Gruppieren von Variablendefinitionen:
Manchmal ist es praktisch und / oder kurz , den Typ einer Reihe von Variablen herauszufiltern:
the_same_type v1, v2, v3;
(Wenn der Grund nur darin besteht, dass der Typname zu lang oder zu komplex ist,
typedef
kann a manchmal besser sein.)Manchmal ist es wünschenswert, Variablen unabhängig von ihrer Verwendung zu gruppieren, um die Menge der Variablen (und Typen) hervorzuheben, die an einer Operation beteiligt sind:
type v1;
type v2;
type v3;
Dies unterstreicht die Gemeinsamkeit des Typs und macht es ein wenig einfacher, ihn zu ändern, während eine Variable pro Zeile beibehalten wird, die das Kopieren, Einfügen,
//
Kommentieren usw. erleichtert .Wie so oft in der Programmierung, kann die eine Praxis in den meisten Situationen einen eindeutigen empirischen Nutzen haben, die andere Praxis kann in einigen Fällen wirklich überwältigend besser sein.
quelle