Initialiserungsliste
-
Hey!
ich habe gerade gelesen, dass eine Initialisierungsliste benutzt werden MUSS, wenn man konstante Membervariablen oder REferenzen als Membervariablen benutzt.
Warum ist das denn so?
Danke!
-
Weil konstante Variablen und Referenzen initialisiert werden müssen.
-
Stimmt es (habe dazu auch was gelesen), dass bei Eintritt in den Konstruktor allen Membervariablen (wenn man keine Init-liste benutzt hat) ein Defaultwert zugewiesen wird und dieser dann erst überschrieben werden würde, wenn man dann sowas wie macht:
Foo::Foo(int a, int b) { membervar1 = a; membervar2 = b; }danke!
-
Jain. Membervariablen mit einem Parameterlosen Konstruktor werden initialisiert (= deren Konstruktor wird aufgerufen). Bei builtin Typen wie int, long, double, char* wird einfach nur Speicher reserviert. Der Wert einer solchen uninitialisierten Variable und der lesende Zugriff auf eine solche Variable sind undefiniertes Verhalten (alles kann passieren, das willst du sicher nicht), bis ihr ein Wert zugewiesen wurde.
-
Ja, aber bis die dann im Konstruktor zugewiesen werden vergehen ja nur Millisekunden.
Ich habe halt gelesen, dass man das machen MUSS?!
-
blub85 schrieb:
Ich habe halt gelesen, dass man das machen MUSS?!
Ja, fuer Referenzen und const Member MUSS man die Initialization List nehmen.
-
@blub85
Ohne Initializer-Liste ist vergleichbar mitvoid EineFunktion() { VariablenTyp variable; variable = irgendwas; // ... }Mit Initializer-Liste ist vergleichbar mit
void EineFunktion() { VariablenTyp variable(irgendwas); // ... }Was cooky451 meint:
class Foo { public: Foo() // nix hier { WarteEineHalbeStunde(); m_var = 123; } private: int m_var; };m_var wird "un-initialisiert" erzeugt.
Dann warten wir ne halbe Stunde. In der Zeit wird m_var aber nicht gelesen.
Kann gar nicht, kennt ja noch keiner die Adresse von m_var (WarteEineHalbeStunde() ist in diesem Beispiel keine Memberfunktion von Foo!).Das ist vollkommen OK.
Was dagegen nicht OK ist, ist sowas:
class Foo { public: Foo() // nix hier { int blossMalGucken = m_var; m_var = 123; } private: int m_var; };Das gibt undefiniertes Verhalten.
Und zwar weil m_var gelesen wird, bevor es initialisert wurde. Das darfst du laut Standard nicht.
Wie lange irgendwas dauert ist dabei vollkommen irrelevant.
-
Okay, danke für die Codebeispiele.
Allerdings habe ich gelesen, dass man das nur bei konstanten und Referenzmembern machen muss mit der Initialisierungsliste?!?
In dem Bsp. oben kommt ja keine konstante vor. Dennoch verstehe ich den potentiellen Fehler, der dadurch entstehen kann...
-
blub85 schrieb:
Allerdings habe ich gelesen, dass man das nur bei konstanten und Referenzmembern machen muss mit der Initialisierungsliste?!?
http://www.c-plusplus.net/forum/p2198453?highlight=basisklasse#2198453
-
@blub85
Was ist denn so schwer zu verstehen?
Du musst Zeugs erstmal schreiben bevor du es lesen darfst. WIE ist dabei ganz egal. Also Init-Liste ist gut, normale Zuweisung ist auch gut. Nur immer erst schreiben, dann darf man erst lesen.
-
Und im Normalfall würde ich die Initialisierungsliste den Zuweisungen vorziehen. Erstere reicht meist aus. Es sei denn, du hast gute Gründe, einzelne Member erst später zu initialisieren.
-
Nexus schrieb:
später zu initialisieren.
:p Da hast du nun einen Widerspruch in sich gebaut.
-
Gugelmoser schrieb:
Nexus schrieb:
später zu initialisieren.
:p Da hast du nun einen Widerspruch in sich gebaut.
Wo denn?
-
@Gugelmoser
Nene, das passt schon.
Bestimmte Typen (Integers, Floats, Zeiger) kann man "uninitialisiert" erzeugen.
Dann macht "später initialisieren" schon Sinn.
-
hustbaer schrieb:
@Gugelmoser
Nene, das passt schon.
Bestimmte Typen (Integers, Floats, Zeiger) kann man "uninitialisiert" erzeugen.
Dann macht "später initialisieren" schon Sinn.Wie meinst du das hustbar?
class foo { private: int i; public: foo() // Wenn i doch hier definiert wird... { // ...kann doch ab hier keine Initialisierung mehr stattfinden... i = 7; // ...sondern nur noch eine Zuweisung. } };Was versteht ihr also unter später initialisiern?
-
Gugelmoser schrieb:
class foo { private: int i; public: foo() // Wenn i doch hier definiert wird... { // ...kann doch ab hier keine Initialisierung mehr stattfinden... i = 7; // ...sondern nur noch eine Zuweisung. } };Was versteht ihr also unter später initialisiern?
Die Variable i ist nicht initialisiert, sie enthaelt einen undefinierten Wert, denn sie wurde nie initialisiert. Deswegen ist i = 7 eine Initialisierung.
-
icarus2 schrieb:
Gugelmoser schrieb:
class foo { private: int i; public: foo() // Wenn i doch hier definiert wird... { // ...kann doch ab hier keine Initialisierung mehr stattfinden... i = 7; // ...sondern nur noch eine Zuweisung. } };Was versteht ihr also unter später initialisiern?
Die Variable i ist nicht initialisiert, sie enthaelt einen undefinierten Wert, denn sie wurde nie initialisiert. Deswegen ist i = 7 eine Initialisierung.
Ok, dann verstehen wir was unterschiedliches unter Initialisierung. Für mich beinhaltet eine Initialisierung immer eine Definition... Folglich unterscheidest du nicht zwischen Initialisierung und Zuweisung, oder wie?
-
icarus2 schrieb:
Deswegen ist i = 7 eine Initialisierung.
i = 7 ist eine Zuweisung. Und zwar immer. Zugegeben: Bei einem simplen int macht das hier keinen wirklichen Unterschied, aber das ändert nix an der Terminologie.
-
Es ist sehr heikel unter welchen Umstaenden etwas initialisiert wird.
Zum Beispiel hier wird i nicht initialisiert:
class foo { public: int i; foo() { // x ist hier nicht initialisiert } }; int main() { foo f; cout << f.i << endl; }Ich habe vorher gegoogelt und keine genauen Informationen dazu gefunden. Scott Meyers meint mal soll einfach immer alle Variablen initialisieren, da die Regeln viel zu kompliziert seien.
-
Also so kompliziert sind die Regeln jetzt nicht...
-
dot schrieb:
Also so kompliziert sind die Regeln jetzt nicht...
Aber warum soll dann i = 7 immer eine Zuweisung sein? Vielleicht habe ich eine falsche Definition von Initialisierung im Kopf. Aber i = 7 ist doch eine Initialisierung weil der Variable i vorher noch kein Wert zugewisen wurde. Sie hat bloss uninitialisierten Speicher bekommen. Dann waere i = 7 doch eine Initialisierung?