Initlist in constructor + order
-
Beispiel:
class DataClass { public: DataClass(int size) : m_size(size), m_data(new double[m_size]) {} private: int m_size; double* m_data; };Also wenn du irgendwelche Abhängigkeiten drin hast.
Wenn du hier die Liste vertauschst, hast du ja m_size noch keinen Wert zugewiesen und das klappt nicht.Also das Beispiel ist vielleicht nicht das schönste weil man ja auch new double[size] machen könnte, aber ich denke es drückt die Wichtigkeit der Reihenfolge aus.
-
Die Reihenfolge der Initialisierungen entspricht der Reihenfolge der Attribut-Deklarationen. Wenn du da nicht aufpasst, kommt nichts Gutes bei raus, wie hierbei z.B.:
class A { private: int a; int b; public: A() : b(7), a(b) {} // schlecht --> a wird mit b initialisiert, b hat aber einen undefinierten Wert. }; int main() {}
-
aso ja das ist klar.
dachte eher an ganz was anderes. danke!
-
drakon schrieb:
struct foo { foo (): value ( obj->get_value () ), // 2. obj ( new some_object () ) // 1. {} some_object* obj; int value; };Dieses Beispiel ist korrekt, da hast du doch kein undefiniertes Verhalten.
Die Reihenfolge der Initialisierungen hängt von der Reihenfolge der Attribut-Deklarationen ab.
Bei deinem Beispiel wird der Zeiger zuerst initialisiert und danach greifst du auf get_value zu.
-
Dweb schrieb:
Die Reihenfolge der Initialisierungen entspricht der Reihenfolge der Attribut-Deklarationen. Wenn du da nicht aufpasst, dann kommt Murx raus, wie hierbei z.B.:
class A { private: int a; int b; public: A() : b(7), a(b) {} // schlecht --> a wird mit b initialisiert, b hat aber einen undefinierten Wert. }; int main() {}Das bin ich dagegen. Es kommt auf die Reihenfolge in der Initialisierungsliste an, nicht auf die Reihenfolge der Attributdeklaration. Das Beispiel so wie es ist funktioniert einwandfrei.
-
Oh jetzt hab ich Mist erzählt. Sorry. Du hattest wirklich Recht. Es kommt auf die Reihenfolge der Deklaration an.
Das Beispiel hab ich mal erweitert:
#include <iostream> struct A { int a; int b; A() : b(7), a(b) {} }; int main() { A a; std::cout << "a.a=" << a.a << std::endl; std::cout << "a.b=" << a.b << std::endl; }Ausgabe ist:
a.a=0
a.b=7Also bitte vergesst was ich geschrieben hab ^^.
-
Dweb schrieb:
drakon schrieb:
struct foo { foo (): value ( obj->get_value () ), // 2. obj ( new some_object () ) // 1. {} some_object* obj; int value; };Dieses Beispiel ist korrekt, da hast du doch kein undefiniertes Verhalten.
Die Reihenfolge der Initialisierungen hängt von der Reihenfolge der Attribut-Deklarationen ab.
Bei deinem Beispiel wird der Zeiger zuerst initialisiert und danach greifst du auf get_value zu.
@drakon:
Da würde ich dich auch gerne nochmal fragen ob du das nicht vertauschst hast, ich war nämlich auch der Meinung die Dweb vertritt.
Nicht dass ich hier jetzt was falsch verstehe :pLg freeG
-
Ja. Wir sind hier alle ein wenig verwirrt.
Sollte während Prüfungszeit nichts posten.
Hier nochmal klipp und klar aus dem Standard:
12.6.2/5 schrieb:
— Then, nonstatic data members shall be initialized in the order they were declared in the class definition
(again regardless of the order of the mem-initializers).Es kommt auf die Reihenfolge in der Klassendefinition an. Mein obiges Beispiel ist in der Tat korrekt und das ist, denke ich der wichtigte Punkt, dass man sich eben nicht auf die Reihenfolge in der Initialisierungsliste verlässt und da dann verwirrt ist, weil sich das nicht sequentiell verhält.
-
Der g++ spuckt normalerweise sogar eine warning aus wenn die Reihenfolge in der Initliste von der Reihenfolge der Deklarationen abweicht...
-
Also als Hilfe, wenn man sich es anders nicht merken kann:
Member müssen in der umgekehrten Reihenfolge zerstört werden wie sie konstruiert wurden. Jetzt kann der Konstruktor aber in einer ganz anderen Übersetzungseinheit stehen als der Destruktor. Woher sollte der Compiler beim compilieren des Destruktors nun die korrekte Reihenfolge kennen, wenn diese der Init-Liste des Konstruktors zu entnehmen wäre, den er gar nicht sieht?