Anfägerfrage zu new und Zeigern



  • Und zwar gehts es um einen Verständnisfrage:

    Habe eine Klasse erstellt "CRaumschiff" und eine davon vererbte Klasse "CMinenleger".

    Wenn ich jetzt einen Zeiger der Klasse "CRaumschiff *Schiff;" erstelle wird ja erstmal nur ein leerer Zeiger des Datentypes "CRaumschiff" erstellt, richtig ?

    Durch den Befehl "Schiff = new CMinenleger;" wird eine Instanz von CMinenleger erstellt.

    Jetzt weiß ich nicht genau wie das abläuft. Der "new" Befehl gibt ja eine reservierte Adresse im Speicher zurück, welche dann Schiff hat.

    Meine Frage ist, wieso hier eine neue Instanz erzeugt wird von CMinenleger anstatt nur eine reservierte Adresse ...

    Ich hoffe ihr versteht mein Problem,

    Danke im Vorraus,
    Coxerino



  • Was heisst "reservierte Adresse"... Das was new zurückgibt ist die Adresse der neuen Instanz im Speicher. Und die steht dann in deinem Zeiger.
    Wenn du jetzt delete pDeinZeiger aufrufst, steht weiterhin die selbe Adresse drin, aber das Objekt dahinter existiert nicht mehr.



  • D.h. der "new" Befehlt liefert nicht nur die Adresse des reservierten Speichers sondern erstellt auch eine Instanz ?

    Wie kann ich denn dann auf die Instanz direkt zugreifen ? Über "schiff" geht es ja nicht, da dies ja nur ein Zeiger auf den Speicher ist wo sich die Instanz befindet oder ?



  • lies ein grundlagen-tutorial.



  • vorschläger schrieb:

    lies ein grundlagen-tutorial.

    Danke für dein Comment 🙄 , habe schoin gesucht und habe ja auch ein Buch hier, aber irgendwie check ich das trotzdem nicht so ganz 😞



  • Coxerino schrieb:

    D.h. der "new" Befehlt liefert nicht nur die Adresse des reservierten Speichers sondern erstellt auch eine Instanz ?

    Der Operator new erzeugt im Speicher ein neues Objekt der Klasse und liefert einen Zeiger darauf zurück.

    Coxerino schrieb:

    Wie kann ich denn dann auf die Instanz direkt zugreifen ? ...

    z.B. so:

    [cpp]
        Schiff = new CMinenleger();
    
        //getGeschwindigkeit sei eine Methode der Klasse CRaumschiff oder CMinenleger:
    
        int geschw = Schiff->getGeschwindigkeit(); 
    [/cpp]
    


  • Grundsätzlich kann man "new T()" in 2 Teile trennen:

    1. operator new besorgt speicher und
    2. der Konstruktor von T ("T::T") wird aufgerufen.

    Wenn du schreibst

    T* t = new T();
    

    dann werden beide Schritte (1 und 2) an der Stelle ausgeführt. Es wird also erst Speicher besorgt und dann in den "neuen" Speicher das Objekt reinkonstruiert.

    Wenn kein Speicher besorgt werden konnte wird natürlich auch erst garnicht versucht den Konstruktor aufzurufen (das würde ja schlimm enden).

    Und wenn der Konstruktor eine Exception wirft, dann wird der bereits besorgte Speicher natürlich wieder freigegeben bevor die Exception weiterfliegt.

    Du kannst dir vorstellen dass der erzeugte Code etwa so aussieht (grob, vereinfacht):

    void* operator new(size_t size)
    {
        void* p = ::malloc(size); // speicher besorgen
        if (!p)
            throw std::bad_alloc(); // kein speicher -> exception
        return p;
    }
    
    void operator delete(size_t size, void* p)
    {
        ::free(p); // speicher freigeben
    }
    
    T* new_T()
    {
        void* raw_memory = ::operator new(sizeof(T)); // rohen speicher besorgen
        try
        {
            // ein "T" in dem rohen speicher anlegen
            T* t = new(raw_memory) T(); // ruft quasi raw_memory->T::T() auf
            return t;
        }
        catch (...)
        {
             // irgendwas ist beim anlegen des "T" schiefgegangen -> speicher wieder freigeben...
            ::operator delete(sizeof(T), raw_memory);
            throw; // und exception weiter fliegen lassen
        }
    }
    


  • Hallo,

    vielen dank, ihr habt mir wirklich weitergeholfen...

    top forum 😉

    Grüße Cox


Anmelden zum Antworten