Frage zu Destructor



  • Liebe Leser

    Ich lese aktuell das Buch von Breyman über C++11 und habe eine Frage zu Destruktoren

    Hier die Beispiel klasse. Frage steht unten

    class EIN_SINNLOSES_OBJEKT
    {
    private:
       int    int1;
       int    int2;
       int    *PointerToInt;
    
    public:
    
    EIN_SINNLOSES_OBJEKT() = default;   // Optimal :: Compiler erstellt konstruktor
    ~EIN_SINNLOSES_OBJEKT() = default;  // Optimal :: Compiler erstellt Destruktor
    }
    

    hier die main funktion

    int main
    { 
    EIN_SINNLOSES_OBJEKT  *Obj;  // Konstruktor wir aufgerufen
    Obj.int1 = 4;
    Obj.int2 = 49;
    Obj.PointerToInt = &Obj.int1; // PointerToInt  zeigt auf speicher von int1
    
    } // Destruktor wird aufgerufen
    

    So nun zu meiner Frage.

    Wenn der Destruktor aufgerufen wird, werden ja automtisch alle Objekte in der Klasse zerstört/Gelöscht, wiel dieser vom Compiler generiert wird. Jedoch wie
    funktioniert das beim member "PointerToInt"? Wird nur der Zeiger gelöscht oder auch der Inhalt, worauf er zeit (Speicherfreigabe)?



  • Sebastian Müller schrieb:

    Wenn der Destruktor aufgerufen wird, werden ja automtisch alle Objekte in der Klasse zerstört/Gelöscht, wiel dieser vom Compiler generiert wird.

    Nein. Wenn der Destruktor aufgerufen wird, also pro Aufruf, wird immer nur ein Objekt zerstört. Der Compiler sorgt aber dafür dass an allen Stellen wo Objekte mit "automatic storage duration" "out of scope" gehen, die passenden Destruktoren aufgerufen werden.

    Sebastian Müller schrieb:

    Jedoch wie funktioniert das beim member "PointerToInt"? Wird nur der Zeiger gelöscht oder auch der Inhalt, worauf er zeit (Speicherfreigabe)?

    Es wird natürlich nur der Zeiger gelöscht, das Objekt auf der er zeigt bleibt bestehen.

    Überleg dir einfach was es für Konsequenzen hätte wenn es anders wäre, dann wird dir klar werden dass es eben nicht anders sein kann 😉

    ps: Der Code in deinem Beispiel ist falsch. "Obj" ist ein Zeiger, und Zeiger kann man nicht mit "." dereferenzieren.



  • Lass mich das mal korrigieren:

    int main 
    { 
    EIN_SINNLOSES_OBJEKT  *Obj;  // Pointer auf EIN_SINNLOSES_OBJEKT. Ein Objekt wir erstellt, also wird auch kein Konstruktor
    Obj.int1 = 4;  //Du hast einen Pointer. Zugriff nur über "->" nicht "."
    Obj.int2 = 49; //Hier auch. Außerdem sind die member privat, das geht also doppelt nicht.
    Obj.PointerToInt = &Obj.int1; // PointerToInt  zeigt auf speicher von int1 
    
    } // Destruktor wird aufgerufen
    

    Wenn man das so macht passt es wieder:

    class EIN_SINNLOSES_OBJEKT
    /* ... */ //Member public gemacht
    
    int main
    { 
    EIN_SINNLOSES_OBJEKT Obj;  // Konstruktor wird aufgerufen
    Obj.int1 = 4;
    Obj.int2 = 49;
    Obj.PointerToInt = Obj.int1; // PointerToInt  zeigt auf speicher von int1
    } // Destruktor wird aufgerufen
    

    Zu deiner eigentlichen Frage:
    Der Destructor zerstört das Object. Da "int1", "int2", und "PointerToInt" Member des Objekts sind, wird auch dieser Speicher freigegeben. Der Speicher auf den der Pointer zeigt allerdings nicht, er könnte ja noch an anderer Stelle gebraucht werden.
    Da der Pointer auf einen Member des selben Objekts zeigt ist das hier kein Problem. Wenn es auf etwas anderes zeigen würde, z.B. auf einen mit new angeforderten Speicherbereich, müsstest du diesen auch manuell im Destruktor freigeben.
    Zu jedem new gehört ein delete. Wenn du allerdings nicht über new Speicher anforderst musst du auch nichts freigeben.



  • OK, dann wäre meine Frage ja beantwortet. Danke

    Jedoch eine Sache noch

    "Nein. Wenn der Destruktor aufgerufen wird, also pro Aufruf, wird immer nur ein Objekt zerstört. Der Compiler sorgt aber dafür dass an allen Stellen wo Objekte mit "automatic storage duration" "out of scope" gehen, die passenden Destruktoren aufgerufen werden. "

    Deine Aussage wieder spricht Irgendwie der, die in meinem Buch steht.

    Wird der Destruktor (der vom Compiler) als 3 mal aufgerufen?
    für int1 / in2 / PointerToInt. oder wie meinst du das

    DarkShadow44********************+++
    Die Main Funktion und die Klasse sind in derselben Datei, und daher bekannt. Die Vorwärtsdeklaration hatte ich jedoch vergessen. und das = new OBJ. Jedoch warum fehlt der Adress operator (&) vor Obj.int1. man weist einem Zeiger eine Adresse zu. oder?



  • wenn du das Objekt tatsächlich mit "new" erstellst, wird am Ende des Scopes *kein* Destruktor aufgerufen.



  • Eingebaute Typen (wie alle Integer-Typen, Zeiger etc.) haben keine Destruktoren, von daher werden die auch nicht aufgerufen.

    (Wobei man auch sagen könnte: sie haben schon einen Destruktor, der aber genau *nichts* tut. Die Unterscheidung ist meist nicht wichtig. Laut Standard ist es aber IIRC so dass die erwähnten Typen keinen Destruktor haben. @Arcoth/camper/...: Bitte um Korrektur falls das Blödsinn ist ;))

    In folgendem Beispiel

    struct Foo
    {
        ~Foo()
        {
            // Dinge tun
        } // ***
        std::string a;
        std::string b;
        std::string* pc;
    };
    
    int main()
    {
       Foo f;
    } // <------
    

    Wird beim Pfeili f.~Foo() aufgerufen, also der Destruktor von Foo auf das Objekt f.
    Das ist alles.

    Der Destruktor ~Foo ruft dann wiederrum den std::string Destruktor für seine Member a und b auf, ganz normal als Unterfunktion. Automatisch von Compiler eingefügt, nachdem der ganze Code den man selbst in ~Foo reingeschrieben hat ausgeführt wurde (Stelle "***").

    pc hat wie schon erwähnt keinen Destruktor, also wird da auch nixe aufgerufen.



  • Sebastian Müller schrieb:

    "Nein. Wenn der Destruktor aufgerufen wird, also pro Aufruf, wird immer nur ein Objekt zerstört. Der Compiler sorgt aber dafür dass an allen Stellen wo Objekte mit "automatic storage duration" "out of scope" gehen, die passenden Destruktoren aufgerufen werden. "

    Deine Aussage wieder spricht Irgendwie der, die in meinem Buch steht.

    Wird der Destruktor (der vom Compiler) als 3 mal aufgerufen?
    für int1 / in2 / PointerToInt. oder wie meinst du das

    Dann steht entweder in deinem Buch Mist, oder du hast das falsch verstanden. Wenn ein Objekt zerstört wird, werden alle Member auch zertört. Bei Integern braucht man aber ja aber keinen Destruktor, und bei Zeigern gibts das auch nicht. Außer bei Smartpointern. Aber das sind ja auch wieder Objekte und keine eingebauten Typen. 😉

    Sebastian Müller schrieb:

    Die Main Funktion und die Klasse sind in derselben Datei, und daher bekannt. Die Vorwärtsdeklaration hatte ich jedoch vergessen. und das = new OBJ. Jedoch warum fehlt der Adress operator (&) vor Obj.int1. man weist einem Zeiger eine Adresse zu. oder?

    Wie meinst du ?
    Ändert doch nichts dran dass du einen Pointer hast und mit "." drauf zugreifst.
    Das mit dem Adress operator, der ist irgendwie beim C&P verloren gegangen, der darf natürlich nicht fehlen. 😃


Anmelden zum Antworten