Wie wichtig ist es, Variablen zu initialisieren?
Vermeidet eine ordnungsgemäße Initialisierung Speicherlecks oder hat sie Leistungsvorteile?
Wie wichtig ist es, Variablen zu initialisieren?
Vermeidet eine ordnungsgemäße Initialisierung Speicherlecks oder hat sie Leistungsvorteile?
null
von den gängigen Compilern auf 0 (oder ) initialisiert , sind jedoch beim Kompilieren für die Veröffentlichung zufälliger Müll. (obwohl mein C ++ Wissen von vor ~ 10 Jahren ist, können sich die Dinge geändert haben)Antworten:
Nicht initialisierte Variablen machen ein Programm nicht deterministisch. Jedes Mal, wenn das Programm ausgeführt wird, kann es sich anders verhalten. Unabhängige Änderungen der Betriebsumgebung, der Tageszeit, der Mondphase und deren Permutationen beeinflussen, wie und wann sich diese Dämonen manifestieren. Das Programm kann eine Million Mal ausgeführt werden, bevor der Fehler auftritt, sie können es jedes Mal tun oder eine weitere Million ausführen. Viele Probleme werden auf "Pannen" zurückgeführt und ignoriert oder Fehlerberichte von Kunden, die als "nicht reproduzierbar" geschlossen wurden. Wie oft haben Sie einen Computer neu gestartet, um ein Problem zu beheben? Wie oft haben Sie zu einem Kunden gesagt: "Noch nie gesehen, lassen Sie es mich wissen, wenn Sie es wieder sehen" - in der Hoffnung, dass sie es nicht tun!
Da die Reproduktion eines Defekts in der Testumgebung nahezu unmöglich sein kann, ist es nahezu unmöglich, ihn zu finden und zu beheben.
Es kann Jahre dauern, bis der Fehler auftritt. Dies gilt häufig für Code, der als zuverlässig und stabil angesehen wird. Es wird vermutet, dass der Fehler in neuerem Code vorliegt - das Aufspüren kann erheblich länger dauern. Eine Änderung des Compilers, ein Compilerwechsel oder sogar das Hinzufügen einer Codezeile können das Verhalten ändern.
Das Initialisieren von Variablen hat einen enormen Leistungsvorteil, nicht nur, weil ein Programm, das korrekt funktioniert, unendlich schneller ist als eines, das nicht funktioniert, sondern die Entwickler weniger Zeit damit verbringen, Fehler zu finden und zu beheben, die nicht vorhanden sein sollten, und mehr Zeit damit, "echte" Arbeit zu leisten.
Der andere wesentliche Vorteil der Initialisierung von Variablen besteht darin, dass der ursprüngliche Autor des Codes entscheiden muss, auf welche Weise sie initialisiert werden sollen. Dies ist nicht immer eine triviale Übung und kann, wenn sie nicht trivial ist, ein Hinweis auf ein schlechtes Design sein.
Speicherlecks sind ein anderes Problem, aber eine ordnungsgemäße Initialisierung kann nicht nur dazu beitragen, sie zu verhindern, sondern auch dazu, sie zu erkennen und die Quelle zu finden - sie ist stark sprachabhängig und das ist wirklich eine separate Frage, die weiter untersucht werden sollte, als ich geben kann in dieser Antwort.
Bearbeiten: In einigen Sprachen (z. B. C #) ist es nicht möglich, nicht initialisierte Variablen zu verwenden, da das Programm nicht kompiliert oder bei Ausführung einen Fehler meldet, wenn dies erledigt ist. Viele Sprachen mit diesen Merkmalen verfügen jedoch über Schnittstellen zu möglicherweise unsicherem Code. Daher muss bei der Verwendung solcher Schnittstellen darauf geachtet werden, keine nicht initialisierten Variablen einzuführen.
quelle
Das Initialisieren einer Variablen, wie Telastyn hervorhob, kann Fehler verhindern. Wenn es sich bei der Variablen um einen Referenztyp handelt, kann durch deren Initialisierung später null Referenzfehler vermieden werden.
Eine Variable eines beliebigen Typs mit einem Standardwert ungleich Null belegt etwas Speicher, um den Standardwert zu speichern.
quelle
Der Versuch, eine nicht initialisierte Variable zu verwenden, ist immer ein Fehler. Daher ist es sinnvoll, die Wahrscheinlichkeit des Auftretens dieses Fehlers zu minimieren.
Der wahrscheinlich häufigste Ansatz für Programmiersprachen zur Minderung des Problems ist die automatische Initialisierung auf einen Standardwert. Wenn Sie also vergessen, eine Variable zu initialisieren, ist dies eher so etwas als so
0
etwas0x16615c4b
.Dies behebt einen großen Prozentsatz von Fehlern, wenn Sie ohnehin eine auf Null initialisierte Variable benötigen. Die Verwendung einer Variablen, die mit einem falschen Wert initialisiert wurde, ist jedoch genauso schlecht wie die Verwendung einer Variablen, die überhaupt nicht initialisiert wurde. In der Tat kann es manchmal sogar noch schlimmer sein, weil der Fehler subtiler und schwieriger zu erkennen sein kann.
Funktionale Programmiersprachen lösen dieses Problem, indem sie nicht nur nicht initialisierte Werte, sondern auch die Neuzuweisung insgesamt nicht zulassen. Das beseitigt das Problem und stellt sich als nicht so schwerwiegende Einschränkung heraus, wie Sie vielleicht denken. Selbst in nicht funktionierenden Sprachen ist Ihr Code viel robuster, wenn Sie darauf warten, eine Variable zu deklarieren, bis Sie einen korrekten Wert zum Initialisieren haben.
Was die Leistung angeht, ist sie wahrscheinlich vernachlässigbar. Im schlimmsten Fall haben Sie bei nicht initialisierten Variablen eine zusätzliche Zuweisung und binden etwas Speicher länger als nötig. Gute Compiler können in vielen Fällen die Unterschiede optimieren.
Speicherlecks sind völlig unabhängig, obwohl ordnungsgemäß initialisierte Variablen in der Regel für einen kürzeren Zeitraum in Reichweite sind und daher für einen Programmierer möglicherweise etwas weniger wahrscheinlich sind, dass sie versehentlich auslaufen.
quelle
Initialisieren bedeutet, dass der Anfangswert wichtig ist. Wenn der Anfangswert wichtig ist, müssen Sie natürlich sicherstellen, dass er initialisiert ist. Wenn es keine Rolle spielt, bedeutet dies, dass es später initialisiert wird.
Unnötige Initialisierung führt zu verschwendeten CPU-Zyklen. Während diese verschwendeten Zyklen in bestimmten Programmen möglicherweise keine Rolle spielen, ist in anderen Programmen jeder einzelne Zyklus wichtig, da die Geschwindigkeit von größter Bedeutung ist. Daher ist es sehr wichtig zu verstehen, was die eigenen Leistungsziele sind und ob Variablen initialisiert werden müssen oder nicht.
Speicherlecks sind ein völlig anderes Problem, bei dem normalerweise eine Speicherzuweisungsfunktion zum Ausgeben und späteren Recyceln von Speicherblöcken erforderlich ist. Denken Sie an ein Postamt. Sie gehen und fragen nach einem Briefkasten. Sie geben dir eins. Sie fragen nach einem anderen. Sie geben dir noch einen. Die Regel lautet: Wenn Sie mit der Verwendung eines Postfachs fertig sind, müssen Sie es zurückgeben. Wenn Sie vergessen, es zurückzugeben, denken sie immer noch, dass Sie es haben, und die Box kann von niemand anderem wiederverwendet werden. Es ist also ein Teil des Speichers gebunden und wird nicht verwendet, und dies wird als Speicherverlust bezeichnet. Wenn Sie irgendwann immer wieder nach Boxen fragen, wird Ihnen der Speicher ausgehen. Ich habe das zu stark vereinfacht, aber das ist die Grundidee.
quelle
Wie andere sagten, kommt es auf die Sprache an. Aber ich werde meine Java- (und Effective Java-) Ideen zum Initialisieren von Variablen demonstrieren. Diese sollten für viele andere höhere Sprachen verwendbar sein.
Konstanten und Klassenvariablen
Klassenvariablen -
static
in Java mit markiert - sind wie Konstanten. Diese Variablen sollten normalerweise endgültig sein und direkt nach der Definition mithilfe=
oder innerhalb eines Klasseninitialisiererblocks initialisiert werdenstatic { // initialize here }
.Felder
Wie in vielen höheren Ebenen und Skriptsprachen wird den Feldern automatisch ein Standardwert zugewiesen. Für Zahlen und
char
dies ist der Nullwert. Für Strings und andere Objekte wird es seinnull
. Jetztnull
ist gefährlich und sollte sparsam eingesetzt werden. Daher sollten diese Felder so schnell wie möglich auf einen gültigen Wert gesetzt werden. Der Konstruktor ist normalerweise ein perfekter Ort dafür. Um sicherzustellen, dass die Variablen während des Konstruktors festgelegt und anschließend nicht geändert werden, können Sie sie mit demfinal
Schlüsselwort markieren .Versuchen Sie, dem Drang zu widerstehen,
null
eine Art Flagge oder einen besonderen Wert zu verwenden. Es ist besser, z. B. ein bestimmtes Feld einzuschließen, um den Status zu halten. Ein Feld mit dem Namenstate
, das die Werte einerState
Aufzählung verwendet, wäre eine gute Wahl.Methodenparameter
Da Änderungen an den Werten von Parametern (seien es Verweise auf Objekte oder Basistypen wie Ganzzahlen usw.) vom Aufrufer nicht gesehen werden, sollten Parameter als markiert werden
final
. Dies bedeutet, dass die Werte der Variablen selbst nicht geändert werden können. Beachten Sie, dass der Wert von wandelbaren Objektinstanzen kann geändert werden, kann der Verweis nicht auf Punkt zu einem anderen Objekt oder geändert werden ,null
though.Lokale Variablen
Lokale Variablen werden nicht automatisch initialisiert. Sie müssen initialisiert werden, bevor ihr Wert verwendet werden kann. Eine Methode, um sicherzustellen, dass Ihre Variable initialisiert wird, besteht darin, sie direkt auf einen Standardwert zu initialisieren. Dies sollten Sie jedoch nicht tun. Meistens ist der Standardwert nicht der erwartete Wert.
Es ist viel besser, die Variable nur genau dort zu definieren, wo Sie sie benötigen. Wenn die Variable nur einen einzigen Wert annehmen soll (was für die meisten Variablen in gutem Code gilt), können Sie die Variable markieren
final
. Dies stellt sicher, dass die lokale Variable genau einmal zugewiesen wird, nicht nullmal oder zweimal. Ein Beispiel:Beachten Sie, dass viele Sprachen Sie warnen, wenn eine Variable vor der Verwendung nicht initialisiert wird. Überprüfen Sie die Sprachspezifikationen und Foren, um festzustellen, ob Sie sich keine unnötigen Sorgen machen müssen.
quelle
Es gibt kein Problem mit der Nichtinitialisierung von Variablen.
Das Problem ist nur, wenn Sie eine Variable lesen, die noch nicht geschrieben wurde.
Abhängig vom Compiler und / oder von der Art der Variablen wird die Initialisierung beim Start der Anwendung durchgeführt. Oder nicht.
Es ist üblich, sich nicht auf die automatische Initialisierung zu verlassen.
quelle
Das Initialisieren von Variablen (implizit oder explizit) ist entscheidend. Das Nichtinitialisieren einer Variablen ist immer ein Fehler (sie können jedoch implizit initialisiert werden. Siehe unten). Moderne Complier wie der C # -Compiler (als Beispiel) behandeln dies als Fehler und lassen Sie den Code nicht ausführen. Eine nicht initialisierte Variable ist einfach nutzlos und schädlich. Sofern Sie keinen Zufallszahlengenerator erstellen, erwarten Sie von einem Code ein deterministisches und reproduzierbares Ergebnis. Dies kann nur erreicht werden, wenn Sie mit initialisierten Variablen arbeiten.
Die wirklich interessante Frage ist, ob eine Variable automatisch initialisiert wird oder ob Sie dies manuell tun müssen. Dies hängt von der verwendeten Sprache ab. In C # werden beispielsweise Felder, dh "Variablen" auf Klassenebene, immer automatisch auf den Standardwert für diesen Variablentyp initialisiert
default(T)
. Dieser Wert entspricht einem Bitmuster, das aus allen Nullen besteht. Dies ist Teil der Sprachspezifikation und nicht nur ein technisches Detail der Implementierung der Sprache. Deshalb können Sie sich sicher darauf verlassen. Es ist sicher, eine Variable nicht explizit zu initialisieren, wenn (und nur wenn) die Sprachspezifikation angibt, dass sie implizit initialisiert wird.Wenn Sie einen anderen Wert wünschen, müssen Sie die Variable explizit initialisieren. Jedoch; In C # werden lokale Variablen, dh in Methoden deklarierte Variablen, nicht automatisch initialisiert, und Sie müssen die Variable immer explizit initialisieren.quelle