Verschiedene Möglichkeiten ?



  • Ich beschaftige mich seit kurzen mit C++ und möchte in den Grundkenntnisse alles genau wissen.
    Ich habe in Tutorials im Internet gesehen, das es mehrere Möglichkeiten gibt einen Konstruktor umzusetzen.
    Im folgenen Beispiel gibt es 2 Möglichkeiten, die scheinbar zum selben Ergebnis führen. Die 2te Möglichkeit ist mir verständlich die 1te eher nicht so.
    Was ist der Untschied zwischen beiden Möglichkeiten

    class KlasseA {
    public:
     int WertA;
     KlasseA(int ParaA) : WertA(ParaA) { };    // 1. Möglichkeit
     KlasseA(int ParaA) { WertA = ParaA; };   // 2. Möglichkeit
    };
    

    Im folgenden Fall gibt es wieder 2 Möglichkeiten. Gibt es hier auch
    Unterschiede ?

    Zeiger->Variable;      // 1. Möglichkeit
    
    (*Zeiger).Variable;    // 2. Möglichkeit
    

    mfg



  • In der ersten Varianten werden die Werte der Variablen gesetzt, BEVOR der Scope des Anweisungsblock betreten wird( Alles zwischen den {} )

    Sinn: Z.B. wenn du eine Variable als constant deklariert hast, stehst du ja in der Zwickmühle.

    - Du kannst der nichtstatischen Konstanten in der Deklaration keinen Wert zuweisen, denn es exisitiert ja noch kein Speicherplatz dafür.

    -Du kannst aber innerhalb der {} ihr keinen Wert zuweisen, denn dann wär es ja keine Konstante mehr.

    -Wat nu 😕 ➡ Variante 1 💡



  • 1. Beispiel:
    Das erste ist eine Intialisierung und das andere eine Wertzuweisung. Bei konstanten Membern musst du die Initalisierung wählen. Bei eigenen Typen wird einmal den Copy-C'tor aufgerufen und das andere mal der Zuweisungsoperator.

    2. Beispiel:
    Kein Unterschied, der -> ist nur eine Vereinfachung.



  • Pavodi schrieb:

    class KlasseA {
    public:
     int WertA;
     KlasseA(int ParaA) : WertA(ParaA) { };    // 1. Möglichkeit
     KlasseA(int ParaA) { WertA = ParaA; };   // 2. Möglichkeit
    };
    

    Noch eine Kleinigkeit:

    Beim erstellen eines Objektes wird natürlich zuerst der nötige Speicher reserviert und dann initialisiert (man möchte ja keinen "rohen" Speicher haben). Bei der ersten Möglichkeit wird WertA gleich mit dem wert von ParaA initialisiert. Beim zweiten wird WertA zuerst mit dem default-Wert initialsiert (bei ints AFAIK 0) und dann der Wert zugewiesen. Braucht also mehr Zeitaufwand, da der Speicherbereich zweimal "bearbeitet" wird.
    Und wenns sich nicht um ints handelt, kommt noch das Problem dazu, dass komplexere Datentypen nicht unbedingt einen default-Wert für die Initialisierung haben (Standardkonstruktor ohne Argumente). Deshalb ist die erste Möglichkeit eigentlich immer vorzuziehen.



  • Hi Pumuckl,

    die Member-Ints werden nicht implizit initialisiert.
    Also würden sie auch nicht doppelt initialisiert.



  • Abgesehen davon, was meine Vorredner schon sagten:

    o neben Konstanten die einzige Möglichkeit, Member-Referenzen zu initialisieren, sonst meckert der Compiler.
    class A { int &val; A(int v) : val(v) {} };

    o Doppelte Initialisierung (was die Vorredner schon sagten etwas präzisiert): einfache Datentypen (int, short usw.) werden in C++ nicht explicit initialisiert und daher auch nicht doppelt beschrieben. Daher haben beide Varianten keinen Unterschied. Für komplexere Objekte (struct/class) bedeutet die erste Variante eine direkte Initialisierung, während bei der zweiten Variante erst der Default-Konstruktor aufgerufen wird und dann der operator =. Das bedeutet zwei Schreibzugriffe und damit mehr Arbeit. Bei der Optimierung kann der Compiler allerdings beide Schritte zu einem vereinen (der MS6.0 kann das z.B.), so dass sich praktisch wiederum keine Unterschiede ergeben.



  • Was noch nicht erwähnt wurde, ist der Aufruf des Basisklassen-Konstruktors, z.B.

    class Base
    {
       Base(int x);
    
    private:
       int m_x;
    };
    
    class X : public Base
    {
       X(int x);
    };
    
    X::X(int x)
      : Base(x)   // <- Initialisierung der Basisklasse
    {
    }
    

Anmelden zum Antworten