Eine Stilfrage



  • Hallo,

    ist es guter C++-Stil ganz gewöhnliche Membervariablen per Initialisierungsliste zu initialisieren?


  • Administrator

    daersc schrieb:

    ist es guter C++-Stil ganz gewöhnliche Membervariablen per Initialisierungsliste zu initialisieren?

    Was sind "ganz gewöhnliche" Membervariablen? Oder was sind "ungewöhnliche" Membervariablen? 😃
    Und ich initialisiere alle Membervariablen per Initialisierungsliste. Denn in der Initialisierungsliste ruft man direkt den Konstruktor auf, wenn das Objekt konstruiert wird. Wenn man eine Variable nicht in der Initialisierungsliste initialisiert, dann wird deren Standardkonstruktor aufgerufen. Wenn man im Konstruktor dann dieser Variable etwas zuweist, macht man eine Kopie. Also hat man schlussendlich einen unnötigen Schritt gemacht.

    Grüssli



  • beide versionen haben vor- und nachteile. ich halte beides für guten stil. kommt halt drauf an. ich kenne leute, die machen eigentlich alles in initialisiererlisten. naja, manchmal wirds häßlich. und alles ohne initialisiererlisten geht natürlich nicht.
    ich benutze sie nicht mehr so intensiv aber hab gar nix dagegen, code zu lesen, der sie intensiv benutzt.



  • volkard schrieb:

    beide versionen haben vor- und nachteile.

    Was sind denn die Vorteile von späterer Zuweisung? Ausser dass man einen Member verzögert initialisieren will, weil er noch von irgendwas abhängig ist, fällt mir jetzt nicht gerade etwas ein.

    Bei der Initialisierungsliste muss man halt aufpassen, dass die Member in der Reihenfolge der Deklaration initialisiert werden...



  • mit dme neune standard geht das ja endlich im header



  • standardstil schrieb:

    mit dme neune standard geht das ja endlich im header

    Als ob das besser wäre -.-



  • was ist daran schlechter?



  • unskilled schrieb:

    standardstil schrieb:

    mit dme neune standard geht das ja endlich im header

    Als ob das besser wäre -.-

    Ich habe mir in dem Punkt noch nicht den neuen Standard angeschaut, sehe hier aber kein schlechten Stil. Ansonsten ziehe ich aber Grundsätzlich die Initialisierungsliste vor.

    volkard schrieb:

    ich kenne leute, die machen eigentlich alles in initialisiererlisten. naja, manchmal wirds häßlich.

    Dann kennst du nun noch einen weiteren. Derzeit sehe ich keinen einzigen Grund die Initialisierungsliste (alleine schon aus Konsistenzgründen) nicht für alle Variablen zu verwenden. Hässlich wird das meiner Meinung nach nur wenn die Klasse zuviele Member besitzt (das ist dann aber eher ein Design-, und nicht ein Initialisierungsproblem).

    cu André



  • Initlisten sind schneller, weil der ganzen MeberVar Chunk per MemCopy in die Instanz kopiert wird. Das ist dann nur ein Copy-Befehl.

    Wenn man alle Member einzeln initialisiert, dann wird pro Member einmal kopiert.

    Initialisierungslisten verwendet man für Klassen, von der sehr viele Instanzen erzeugt werden. Weil der Scheiss so schwierig zu lesen ist, sollte man ihn nur verwenden, wenn nötig.

    Typischer Anwendungsfall für Init-Listen: Vektor-Klassen in 3D Anwendungen. Davon hat man oft ein paar tausend Instanzen.



  • Ich verwende sie immer. Der g++ hat 'ne Kompileroption -Weffc++, die warnt, wenn bestimmte Sachen nicht in der Initialisierungsliste des Konstruktors initialisiert werden. Zumal sind die meisten Anfaengerfehler (auch hier im Forum zu beobachten) meist falsche oder nicht initialisierte Variablen.



  • Peter_Lustig schrieb:

    Initlisten sind schneller, weil der ganzen MeberVar Chunk per MemCopy in die Instanz kopiert wird. Das ist dann nur ein Copy-Befehl.
    Wenn man alle Member einzeln initialisiert, dann wird pro Member einmal kopiert.

    wohl kaum.
    unterschiede hats nur, wenn die konstruktoren oder zuweisungsoperatoren teure dinge tun, wie bei std::string.
    attribute vom typ int oder double kannste drch initialisiererlisten nicht beschleunigen.
    entsprechend sind sie auch nur für sachen wie std::string notwendig und alle weitere ist kür.



  • Wie kommste denn darauf?



  • volkard schrieb:

    Peter_Lustig schrieb:

    Initlisten sind schneller, weil der ganzen MeberVar Chunk per MemCopy in die Instanz kopiert wird. Das ist dann nur ein Copy-Befehl.
    Wenn man alle Member einzeln initialisiert, dann wird pro Member einmal kopiert.

    wohl kaum.
    unterschiede hats nur, wenn die konstruktoren oder zuweisungsoperatoren teure dinge tun, wie bei std::string.

    Es mag sein, das es bei integralen Datentypen kaum oder keinen Unterschied macht. Es ist aber meiner Meinung nach schlechter Stil etwas in einem Fall zu machen, in einem Anderen aber nicht. Zumal es zumindest bei mir die Wahrscheinlichkeit reduziert eine Variable zu vergessen (Ich versuche die Initialisierungsliste immer mit den Membern identisch zu halten, die otionale Warnung wie im gcc scheinbar möglich würde ich mir auch bei anderen Compilern wünschen).

    Initialisierungslisten meiner Meinung nach zwar etwas, aber nicht wesentlich, komplizierter zu lesen.

    cu André



  • asc schrieb:

    Initialisierungslisten meiner Meinung nach zwar etwas, aber nicht wesentlich, komplizierter zu lesen.

    Wenn man die Member schön untereinander gliedert, finde ich das nicht mal weniger übersichtlich als Zuweisungen.

    Aus meiner Sicht können Zuweisungen in Ausnahmefällen okay sein (wenn verpätete Initialisierung oder keine Initialisierung aus Performancegründen notwendig ist), aber für die meisten Member sollte man eigentlich Initialisierungslisten verwenden. Zumal es für gewisse Fälle gar keine Alternative gibt.

    standardstil schrieb:

    was ist daran schlechter?

    Das finde ich total schlimm. Keine Ahnung, was sich die Standard-Leute dabei gedacht haben. Als ob es nicht schon genügend Inkonsistenzen und für jedes Problem mehrere sprachliche Ansätze gäbe - nein, man muss jetzt auch noch Member direkt bei der Deklaration initialisieren können. 🙄



  • Habs nachgemessen. Initlisten sind im Release und im Debug Built bei VC 9 (WinXp Professional 2 GB RAM) schneller. Auch bei integralen Datentypen. Der Speedgain betrug bei meinem Benchmark ca. 10% bei diesen 5 Member Vars

    int      m_a;
        double   m_b;
        int      m_c;
        float    m_d;
        unsigned m_e;
    


  • Nexus schrieb:

    standardstil schrieb:

    was ist daran schlechter?

    Das finde ich total schlimm. Keine Ahnung, was sich die Standard-Leute dabei gedacht haben. Als ob es nicht schon genügend Inkonsistenzen und für jedes Problem mehrere sprachliche Ansätze gäbe - nein, man muss jetzt auch noch Member direkt bei der Deklaration initialisieren können. 🙄

    Stimmt, jetzt könnte man diese komischen initialisierungslisten weg werfen, aber dann würden die alten programme nicht mehr funktionieren. Wenn Member schon immer direkt bei der Deklaration initialisiert worden wären und jetzt Initialisierungslisten dazu kommen würden, dann würden alle Initialisierungslisten dämlich finden.



  • standardstil schrieb:

    Wenn Member schon immer direkt bei der Deklaration initialisiert worden wären und jetzt Initialisierungslisten dazu kommen würden, dann würden alle Initialisierungslisten dämlich finden.

    Dir ist aber schon bewusst, dass es mehrere Möglichkeiten gibt, Member einer Klasse zu initialisieren?

    Von daher finde ich die "einheitliche" Initialisierung bei der Deklaration alles andere als gut. Sobald man eine komplexere Klasse hat, hat diese auch mehrere Konstruktoren. Und sobald dies der Fall ist, ist die Initialisierung gleich in der Klassendefinition nicht mehr so einheitlich. Schlussendlich läuft es darauf hinaus, dass gewisse Member in Konstruktoren, gewisse in der Klasse initialisiert werden. Sehr konsistent.



  • Nexus schrieb:

    standardstil schrieb:

    Wenn Member schon immer direkt bei der Deklaration initialisiert worden wären und jetzt Initialisierungslisten dazu kommen würden, dann würden alle Initialisierungslisten dämlich finden.

    Dir ist aber schon bewusst, dass es mehrere Möglichkeiten gibt, Member einer Klasse zu initialisieren?

    Von daher finde ich die "einheitliche" Initialisierung bei der Deklaration alles andere als gut. Sobald man eine komplexere Klasse hat, hat diese auch mehrere Konstruktoren. Und sobald dies der Fall ist, ist die Initialisierung gleich in der Klassendefinition nicht mehr so einheitlich. Schlussendlich läuft es darauf hinaus, dass gewisse Member in Konstruktoren, gewisse in der Klasse initialisiert werden. Sehr konsistent.

    na, wenn du meinst...



  • PeterLustig schrieb:

    Auch bei integralen Datentypen. Der Speedgain betrug bei meinem Benchmark ca. 10%

    aha. 😮
    meine info war aus einem buch. habs geglaubt, ohne selber zu messen.
    ok, dann werd ich wohl mal vermehrt zu initialisiererlisten greifen.



  • volkard schrieb:

    aha. 😮
    meine info war aus einem buch. habs geglaubt, ohne selber zu messen.
    ok, dann werd ich wohl mal vermehrt zu initialisiererlisten greifen.

    Und das passiert Jemanden der aufschreit, wenn einer von vorzeitigen Optimierungen abrät... ;p


Anmelden zum Antworten