Reihenfolge in der Initialisierungsliste



  • Warum gibt denn dieser Code eine Warning? (g++ - Wall)

    class Foo
    {
    public:
    	Foo()
    		: b(5)
    		, a(10)
    	{
    	}
    
    	int a;
    	int b;
    };
    

    test.cpp: In constructor Test::Test()': test.cpp:9: warning:Test::b' will be initialized after
    test.cpp:8: warning: `int Test::a'

    In welcher Situation kann denn sowas gefährlich werden?



  • struct foo {
       int a;
       int b;
    
       foo () : b(5), a(b) {}
    };
    
    int main() {
       foo f;
       cout << f.a << '\n' << f.b << '\n';
    }
    

    Die Reihenfolge der Initialisierung der Elementvariablen folgt immer der Reihenfolge der Deklarationen ebendieser in der Klassendefinition und nicht der der Elementinitialisierungsliste eines Konstruktors.



  • davie schrieb:

    Die Reihenfolge der Initialisierung der Elementvariablen folgt immer der Reihenfolge der Deklarationen ebendieser in der Klassendefinition und nicht der der Elementinitialisierungsliste eines Konstruktors.

    jo. und jetzt bitte noch die begründung, warum das so sein muß, damit ich mir es besser merken kann.



  • Ja, das war mir schon klar.

    Nur ich verstehe nicht warum die "falsche" Reihenfolge eine Warnung bringt.

    Oder könnt ihr euch eine Situation vorstellen, wo die Reihenfolge eine Rolle spielt?



  • ord€r schrieb:

    Oder könnt ihr euch eine Situation vorstellen, wo die Reihenfolge eine Rolle spielt?

    :_len(strlen(str)),_str(new char[len+1])
    


  • volkard schrieb:

    jo. und jetzt bitte noch die begründung, warum das so sein muß, damit ich mir es besser merken kann.

    Und das mitten in der Nacht? 🙄
    So wie es ist, ist es effizienter, denn der Compiler müsste sonst irgendwo noch Zusatzinformationen anbringen (Deshalb hab ich geschrieben "ein"es Konstruktors) und diese bei den Destruktoraufrufen der Elemente berücksichtigen und es ist, so wie es ist, einheitlich.
    Es ist schlicht und einfach einfacher für die Compilerbauer.



  • War das nicht so, dass alle Datenelemente einer Klasse in der umgedrehten Reihenfolge ihrer Konstruierung dekonstruiert werden.
    Dadurch müssten dann zusätzliche Informationen über die Reihenfolge der Konstruierung mitgespeichert werden.



  • Scott Meyers schrieb in Effektiv C++ Programmieren (alte Ausgabe Seite50, kleine Zusammenfassung) schrieb:

    Man soll die Elemente in der Initialisierliste in der Reihenfolge ihrer Deklaration aufführen:

    Weil Klassenelemente in der Reihenfolge ihrer Deklaration in der Klasse initialisiert werden, die Reihenfolge in der sie in der Intitialiesierungsliste stehen ist ohne Bedeutung.

    MfG Max



  • C Newbie schrieb:

    War das nicht so, dass alle Datenelemente einer Klasse in der umgedrehten Reihenfolge ihrer Konstruierung dekonstruiert werden.
    Dadurch müssten dann zusätzliche Informationen über die Reihenfolge der Konstruierung mitgespeichert werden.

    Nein, denn das ist in der Klassendefinition ja festgelegt, und wenn du eine Klasse löschst (auto oder delete), dann muss die Klassendefinition ja sowieso feststehen. Ansonsten müssten entweder die Konstruktoren alle irgendwie zugänglich sein, was widerum mehr Abhängigkeiten bedeutet- oder es müsste eben die Konstruktionsreihenfolge irgendwo gespeichert werden (zur Laufzeit).



  • In Effektiv C++, steht genau das drin was Davie gesagt hat.
    Schreibe deine Variablen immer in der Reihenfolge in die Initialisierungsliste,
    in der du sie deklariert hast. Sollte die Variable a von der Variablen b abhängen,
    so ist diese Variable ein Fall für den Rumpf des Konstruktors, oder aber du deklarierst
    sie, so dass es geht(b vor a).



  • davie schrieb:

    volkard schrieb:

    jo. und jetzt bitte noch die begründung, warum das so sein muß, damit ich mir es besser merken kann.

    Und das mitten in der Nacht? 🙄
    So wie es ist, ist es effizienter, denn der Compiler müsste sonst irgendwo noch Zusatzinformationen anbringen (Deshalb hab ich geschrieben "ein"es Konstruktors) und diese bei den Destruktoraufrufen der Elemente berücksichtigen und es ist, so wie es ist, einheitlich.
    Es ist schlicht und einfach einfacher für die Compilerbauer.

    jo. das ist es (fast).
    wenn man *einen* konstruktor hat, könnte der destruktor einfach die im konstruktor kostruierten elemente im destruktor in umgkehrter reihenfolge destruieren. sobald man mehrere konstruktoren hat, die in unterschiedlicher reihenfolge die elemente konstruieren, wären zusatzinfos zur laufzeit nötig, damit der destruktor die richtige reihenfolge kennt.
    (ich schreibe hier nix neues und widerspreche keinem. eigentlich tippe ich aus dem gedächtnis ab, was ich in "effektiv c++ programmieren" las. und wer meinen beitrag jetzt erhellend findet, der lese das buch bitte, es ist echt das beste überhaupt über c++.)
    es ist für die compilerbauer viel einfacher, wenn die abarbeitungsfolge vorher schon klar ist.
    wichtiger aber noch als compilerbauerfaulheit ist mir die volkardfaulheit. ja, sie steht mir fast schon an erster stelle. und siehe da, c++ ist volkardkompatibel. warum? na, weil ich ne klare ansage habe und nicht immer umdenken muß, wenn ich nen zweiten konstruktor baue. (nen zweiten destruktor geht ja nicht). und weil ich weit mehr als die zehnfache zeit des alleinigen schreibens bei der fehlersuche verbringe. alles, was fehler vermeidet bzw früherkennbarer macht, ist gut. un diese klare ansage gehört wirklich voll dazu.


Anmelden zum Antworten