Hintergrund:
Die Initialisierungsliste wurde in C++ eingeführt, um die korrekte und optimale Initialisierung von Klassenmitgliedern vor der Ausführung des Hauptkörpers des Konstruktors zu gewährleisten. Dies resultiert aus der Erfahrung mit C und C++: Für konstante Mitglieder und Referenzen ist es im Körper des Konstruktors nicht möglich, sie zu initialisieren, nur in der Liste.
Problem:
Wenn versucht wird, solche Mitglieder im Körper des Konstruktors anstelle der Initialisierungsliste zu initialisieren, tritt ein Kompilierungsfehler auf. Außerdem führt das Ignorieren der Liste zu einem doppelten Initialisierungsaufruf für Mitgliederobjekte, was sich auf die Leistung auswirkt, insbesondere bei komplexen Initialisierungskonstruktoren.
Lösung:
Es ist optimal, Mitglieder der Klasse über die Initialisierungsliste zu deklarieren und zu initialisieren – insbesondere, wenn es sich um Konstanten (const) oder Referenzen (&) handelt. Die Initialisierungsliste wird VOR der Ausführung des Körpers des Konstruktors verwendet, wenn die Mitglieder der Klasse noch in der Konstruktion sind.
Beispielcode:
class Example { const int value; int& ref; public: Example(int v, int& r) : value(v), ref(r) { /* Körper des Konstruktors */ } };
Wichtige Merkmale:
Was passiert, wenn die Reihenfolge der Mitglieder der Klasse und ihrer Initialisierung in der Liste geändert wird?
Die Initialisierung erfolgt immer in der Reihenfolge, in der die Mitglieder in der Klasse deklariert sind, und nicht in der Reihenfolge, in der sie in der Initialisierungsliste geschrieben sind. Wenn abhängige Mitglieder in "falscher Reihenfolge" initialisiert werden, kann auf nicht initialisierten Speicher zugegriffen werden.
Beispielcode:
class Foo { int x; int y; Foo() : y(2), x(y) {} // x wird ZUERST mit dem Wert vom nicht initialisierten y initialisiert. }
Kann ein const-Mitglied der Klasse im Körper des Konstruktors initialisiert werden?
Nein. Dies führt zu einem Kompilierungsfehler. Nur über die Initialisierungsliste.
Was passiert, wenn ein Referenzmitglied nicht initialisiert wird?
Wenn ein Referenzmitglied nicht initialisiert wird, tritt ein Kompilierungsfehler auf, weil eine Referenz beim Erstellen an ein Objekt "gebunden" sein muss und später nicht mehr geändert werden kann.
In einer Klasse zur Speicherung von Einstellungen wird const std::string und eine Referenz verwendet, der Versuch, diese Mitglieder im Körper des Konstruktors zu initialisieren, führt zu Kompilierungsfehlern oder die Daten werden nicht initialisiert.
Vorteile: Der Anfänger hat den Fehler erkannt und gelernt, Konstruktion von Zuweisung zu unterscheiden.
Nachteile: Kompilierungsfehler, Unmöglichkeit, die Klasse zu verwenden, mögliche unerwartete Fehler während der Initialisierung von Objekten.
Konstanten und Referenzen werden korrekt über die Initialisierungsliste initialisiert. Der gesamte komplexe Initialisierungscode ist in der Liste konzentriert, was die Lesbarkeit erhöht und Fehler verhindert.
Vorteile: Sichere und korrekte Initialisierung der Mitglieder der Klasse, hohe Lesbarkeit, keine Speicherlecks oder undefiniertes Verhalten.
Nachteile: Es kann eine komplexe Initialisierungslogik entstehen, deren Teile ohne zusätzlichen Code nicht so einfach zu testen sind.