Verständnisproblem: Elementinitialisierer
-
Der Sinn der Initialisierungsliste ist es, im Konstruktor nicht den Standardkonstruktor der Member aufzurufen, sondern einen anderen zu wählen. Das hat den Vorteil, dass der Aufruf des Standardkonstruktors gespart werden kann und ist nötig, wenn bestimmte Member keinen Standardkonstruktor haben.
Beispiel:
struct foo { int& i; const int ci; string s; // falsch: foo(int& ref) // bevor die 1. Anweisung ausgeführt wird, werden alle Standardkonstruktoren aufgerufen // Fehler: int& hat keinen Standardkonstruktor { i = ref; // illegal ci = 42; // illegal --> ci hätte undefinierten Wert s = "Hallo"; // operator= wird aufgerufen --> man hätte sich den Standardkonstruktoraufruf sparen können } // besser: foo(int& ref) : i(ref) /* jetzt möglich */, ci(42) /* auch möglich */, s("Hallo") /* Konstruktor string(const char*) wird aufgerufen, Standardkonstruktor wird gespart */ { // keine weiteren Anweisungen nötig } };
In deinem Beispiel ist das egal, allerdings empfehle ich dir, dir die Initialisierungsliste grundsätzlich zugunsten der Konsistenz anzugewöhnen.
-
In deinem oberen Beispiel wird zahl halt doppelt gesetzt. Erst wird es standardmäßig mit 0 initialisiert, und dann wird es im Rumpf des Konstruktors auf z gesetzt. Das untere Beispiel initialisiert zahl direkt mit z. Wenn du dort statt einem einfachen int eine Klasse hast, kann da auch etwas ganz anderes rauskommen. Es wird dort standardmäßig der Konstruktor ohne Parameter aufgerufen um das Objekt zu initialisieren. Soll direkt ein Konstruktor mit Parameter aufgerufen werden, brauchst du den Elementinitialisierer.
-
Hi,
das mit der Initialisierung der Referenzen und Konstanten wusste ich nicht. Dass man Konstanten erst später initialisieren kann, ist ja irre@Tobiking2: Das leuchtet sein. Der Elementinitialisierer hat mich überzeugt.
Vielen Dank
lg, freakC++
-
Tobiking2 schrieb:
In deinem oberen Beispiel wird zahl halt doppelt gesetzt. Erst wird es standardmäßig mit 0 initialisiert, und dann wird es im Rumpf des Konstruktors auf z gesetzt.
Das wage ich zu bezweifeln.
#include <iostream> using namespace std; class CTest { private: int zahl; public: CTest(int); const int& getZahl() const {return zahl;}; }; CTest::CTest(int z = 0) { cout << zahl << endl; // zufälliger Wert, da wird nichts auto. mit 0 initialisiert. } int main() { CTest test(100); getchar(); return 0; }
-
freakC++ schrieb:
Dass man Konstanten erst später initialisieren kann, ist ja irre.
Hä, wie meinst du den das?
Man kann nie etwas "später initialisieren" (initial = Anfang),
man kann nur "später etwas anders zuweisen", was bei Konstanten bekanntlicherweise nicht geht.Initialisierung = Definition mit Defaultzuweisung.
-
Dweb schrieb:
Das wage ich zu bezweifeln.
Hmm, du hast Recht. Aber irgendwie trudelt mir diese Nullinitialisierung bei Membervariablen durch den Kopf. War das vielleicht der Fall wenn man das Objekt per new erzeugt? Oder bin ich da ganz nach Java abgedriftet?
-
Tobiking2 schrieb:
Dweb schrieb:
Das wage ich zu bezweifeln.
Hmm, du hast Recht. Aber irgendwie trudelt mir diese Nullinitialisierung bei Membervariablen durch den Kopf.
Globale Variablen werden automatisch mit 0 initialisiert, falls nichts angegeben wird, oder du hast es mit Java verwechselt
#include <iostream> using namespace std; int i; static int si; int main() { cout << i << endl << si; cin.sync(); cin.get(); return 0; }
-
Ok, das mit "später initialisieren war falsch". Sie werden ja direkt initialisiert. Ich kannte nur diese Methode nicht, doch sie gefällt mir immer mehr.
Danke!
lg, freakC++
-
freakC++ schrieb:
Ok, das mit "später initialisieren war falsch". Sie werden ja direkt initialisiert. Ich kannte nur diese Methode nicht, doch sie gefällt mir immer mehr.
Nur nochmal etwas Klarer:
Die Initialisierung findet ausschließlich in der Initialisierungsliste statt, im Konstruktorrumpf werden nachträgliche Zuweisungen durchgeführt (dein Text deutet an, das du die Zuweisung im Konstruktor weiterhin als Initialisierung betrachtest - umgangssprachlich würde ich dem beipflichten, programmiertechnisch nicht).
-
Tobiking2 schrieb:
Aber irgendwie trudelt mir diese Nullinitialisierung bei Membervariablen durch den Kopf. War das vielleicht der Fall wenn man das Objekt per new erzeugt? Oder bin ich da ganz nach Java abgedriftet?
Bei POD-Objekten führt eine Klammer (Syntax eines Defaultkonstruktor-Aufrufs, es sind jedoch keine Konstruktoren vorhanden) zu einer Null-Initialisierung.
// Konstruktor-Initialisierungsliste MyClass::MyClass() : myPOD() {} // temporäres Objekt POD myPOD = POD(); // new-Ausdruck new POD();
Nicht initialisiert wird das Objekt hingegen in solchen Situationen:
MyClass::MyClass() {} POD myPOD; new POD;