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 aufgerufenSo 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 aufgerufenWenn 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 aufgerufenZu 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 dasDarkShadow44********************+++
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 dasDann 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.