Verständnisfragen zu new Element() und Destruktoren



  • Hallo zusammen, ich arbeite mich zur Zeit in cpp ein und hätte gerne gewusst ob ich folgendes richtig verstanden haben.

    nehmen wir folgenden code :

    Myklasse * a = new Myklasse();

    hier ist :

    1. das = nicht der operator= der in Myklasse steht ?!
    2. wird der Konstruktor aufgerufen, nach beendigung des programms aber kein explizit deklarierte destruktor ?!

    weiterhin wenn ich nun :

    Myklasse * b = a; // das a von oben

    schreibe wird nur der zeiger von b auf die adresse von a gesetzt ?
    hier wird

    1. kein Konstruktor benutzt
    2. keine operator=

    Stimmt das soweit ?

    Danke Vorab, ich hoffe es ist verständlich formuliert



  • tallan schrieb:

    1. das = nicht der operator= der in Myklasse steht ?!

    Nein, das ist der eingebaute operator= für Zeiger.

    tallan schrieb:

    1. wird der Konstruktor aufgerufen, nach beendigung des programms aber kein explizit deklarierte destruktor ?!

    Wenn du new einsetzt, hast du manuelle Speicherverwaltung. Das bedeutet, du (und nicht der Scope) entscheidest über Lebensdauer von Objekten. Um das Objekt zu zerstören und den Speicherbereich hinter dem Zeiger freizugeben, musst du delete einsetzen.

    tallan schrieb:

    weiterhin wenn ich nun :

    Myklasse * b = a; // das a von oben

    schreibe wird nur der zeiger von b auf die adresse von a gesetzt ?
    hier wird

    1. kein Konstruktor benutzt
    2. keine operator=

    Ja, der Zeiger wird gesetzt. Genau genommen kommt auch kein operator= vor, da es sich um eine (POD-)Initialisierung und keine Zuweisung handelt. Von der Klasse Myklasse selbst wird aber ganz sicher nichts aufgerufen, sie müsste für diese Operation nicht einmal vollständig definiert sein.



  • tallan schrieb:

    1. wird der Konstruktor aufgerufen, nach beendigung des programms aber kein explizit deklarierte destruktor ?!

    Wenn du new einsetzt, hast du manuelle Speicherverwaltung. Das bedeutet, du (und nicht der Scope) entscheidest über Lebensdauer von Objekten. Um das Objekt zu zerstören und den Speicherbereich hinter dem Zeiger freizugeben, musst du delete einsetzen.

    erstmal danke für die schnell antwort zum 2ten ahb ich noch ein frage

    das heisst wenn Myklasse einen Desktruktor implementiert hat wird dieser am ende nicht auferufen sondern ich muss explizit z.b per delete a; das objekt löschen ?



  • tallan schrieb:

    das heisst wenn Myklasse einen Desktruktor implementiert hat wird dieser am ende nicht auferufen sondern ich muss explizit z.b per delete a; das objekt löschen ?

    Automatisch nicht nein, alles was mit new erstellt wurde muß auch expliziet mit delete freigegeben haben, tut man das nicht gibt das ein Speicherleck.



  • Und das hat wiederrum zur Folge, dass Arbeitsspeicher auf dem Heap verloren geht - je nach Compiler entweder nur zur Laufzeit oder bei älteren Modellen bis zum Neustart des Computers, wo der RAM ja sowieso hopps geht. 😉



  • wobei modernere betriebssysteme den destruktor automatisch beim verlassen des programmes aufrufen.
    aber es bleibt weiterhin ein schlechter programmierstil, wenn man die objekte nicht selbst zerstört



  • danke das ist mir schon klar das man sie löschen sollte, es ging hier um übungen zur vererbung in denen zu befehlen die ausgaben rausgesucht werden sollten, und ich wollte nur sichergehen das ich die destruktor ausgaben bzw aufrufe ( es war jeweils ein cout in allen methoden ) richtig verstanden habe



  • daersc schrieb:

    wobei modernere betriebssysteme den destruktor automatisch beim verlassen des programmes aufrufen....

    hmmmm, wirklich?
    Also dass ein OS den Speicher wieder freiräumt und ggf. andere OS-verwaltete Ressourcen freigibt (Filehandles, ...), mag ich ja noch glauben. Aber einen Dtor, der vielleicht noch andere "Aufräumarbeiten" erledigt, aufzurufen, traue ich ihm nicht zu.
    Vielleicht packt das eine ausgefeilte Runtimelib ... aber spätestens bei ausgefeilten Abhängigkeiten (bei denen z.B. die Reihenfolge wichtig ist) wird das auch nicht klappen.

    Gruß,

    Simon2.



  • Ich glaube er bezog sich dabei eher auf die Destruktoren die vorhanden sind. Wobei Speicher freigeben der mit new erzeugt wurde ja ansich auch geht man könnte ihn in void* lagern und dann freigeben, das wäre zwar nicht ganz korrekt würde doch aber eigentlich nen Teil des Lecks verhindern?



  • tallan schrieb:

    das heisst wenn Myklasse einen Desktruktor implementiert hat wird dieser am ende nicht auferufen sondern ich muss explizit z.b per delete a; das objekt löschen ?

    Wenn du Objekte auf dem Stack (automatische Speicherklasse) anlegst, werden deren Destruktoren beim Verlassen des Gültigkeitsbereiches (in umgekehrter Deklarationsreihenfolge) aufgerufen:

    int main()
    {
        Myklasse a;
        {
            Myklasse c;
        } // hier wird c zerstört.
        Myklasse b;
    } // hier wird zuerst b und dann a zerstört.
    

    Xebov schrieb:

    Wobei Speicher freigeben der mit new erzeugt wurde ja ansich auch geht

    Natürlich geht das, ganz konventionell mit delete . Worauf willst du hinaus? Drück dich genauer aus.



  • Xebov schrieb:

    Ich glaube er bezog sich dabei eher auf die Destruktoren die vorhanden sind. ...

    Wer ".. bezog sich dabei ..."?
    Und was sind "...Destruktoren die vorhanden sind..." ? (dass nicht vorhandene vom OS auch nicht aufgerufen werden, finde ich jetzt wenig überraschend)

    Gruß,

    Simon2.



  • Xebov schrieb:

    Wobei Speicher freigeben der mit new erzeugt wurde ja ansich auch geht

    Natürlich geht das, ganz konventionell mit delete . Worauf willst du hinaus? Drück dich genauer aus.[/quote]

    Du hast das etwas aus dem Zusammenhang gerissen, ich bezog mich auf Simons Post und wolte damit sagen das ein OS ja evtl tracken könnte welchen Ram das Programm belegt und den rest der nach dem beenden übrig bleibt freigeben köntne von alleine.

    Simon2 schrieb:

    Xebov schrieb:

    Ich glaube er bezog sich dabei eher auf die Destruktoren die vorhanden sind. ...

    Wer ".. bezog sich dabei ..."?
    Und was sind "...Destruktoren die vorhanden sind..." ? (dass nicht vorhandene vom OS auch nicht aufgerufen werden, finde ich jetzt wenig überraschend)

    Wenn ich mit new etwas erzeuge wäre ein Destruktor nicht automatisch vorhanden wenn ich kein delete benutze denn das Objekt lebt ja nach dem beenden als Leck weiter, so meinte ich das.



  • Xebov schrieb:

    Du hast das etwas aus dem Zusammenhang gerissen, ich bezog mich auf Simons Post und wolte damit sagen das ein OS ja evtl tracken könnte welchen Ram das Programm belegt und den rest der nach dem beenden übrig bleibt freigeben köntne von alleine.

    Sorry, der Kontext war mir nicht gleich klar. In der Praxis wird ein Programm beim Beenden den zugesicherten Speicher wieder an das Betriebssystem zurückgeben, vermute ich (also müsste nicht jede Anforderung vom OS selber getrackt werden). Aber besser ist es, man lässt es gar nicht darauf ankommen. Wenn man komplexere Abhängigkeiten hat, können Smart Pointer und RAII sehr nützlich sein.

    Xebov schrieb:

    Wenn ich mit new etwas erzeuge wäre ein Destruktor nicht automatisch vorhanden wenn ich kein delete benutze denn das Objekt lebt ja nach dem beenden als Leck weiter, so meinte ich das.

    Vorhanden (als Funktion) ist der Destruktor trotzdem, auch wenn er nicht aufgerufen wird - es sei denn, du implementierst ihn nicht, was normalerweise aber niemand macht...

    Hm, hat das deine Fragen ungefähr beantwortet? Tut mir leid, wenn meine Antworten zu unpräzise sind, aber deine Fragen waren es auch. 🙂


  • Administrator

    Xebov schrieb:

    Wenn ich mit new etwas erzeuge wäre ein Destruktor nicht automatisch vorhanden wenn ich kein delete benutze denn das Objekt lebt ja nach dem beenden als Leck weiter, so meinte ich das.

    Da fehlen Satzzeichen.
    Ich habe probiert, diese selber einzufügen.
    Ich bin gescheitert.
    Und ich habe auch immer noch nicht verstanden, was du sagen willst.

    Mit kurzen Sätzen kannst du dies vielleicht besser klarstellen.
    Verschachtelte Sätze können schnell zu komplex werden.
    Dies gilt vor allem, wenn man keine Satzzeichen verwendet.
    Oder wenn man zu wenig Satzzeichen verwendet.

    Grüssli 😃



  • Nexus schrieb:

    Hm, hat das deine Fragen ungefähr beantwortet? Tut mir leid, wenn meine Antworten zu unpräzise sind, aber deine Fragen waren es auch. 🙂

    Es war mehr son Mix aus Frage und Feststellung aber macht nix, hab mich da wohl etwas zu ungünstig ausgedrückt.

    Dravere schrieb:

    ...

    😃

    Ich hätte echt Quoten sollen, seite 1 Simons Post.
    OK der Post von Simon wegen dem automatischen Aufruf des Betriebssystems. Da wolte ich dazu sagen das der auf den sich Simon bezog wohl nur existente aufrufbare Destruktoren meint (oder kurz RAII) und nicht Destruktoren die nicht von alleine Aufgerufen werden (wegen new) durchs OS oder wo auch immer. Und habe danach gesagt es wäre ja auch Möglich das das OS den Speicher der Anwendung Trackt und ihn danns elbst freigibt denn das OS weis ja wann sich das Programm verarbschieded hat. Hatte es nur nicht gequotet deswegen war wohl unklar worauf ich mich bezogen hatte.

    So ich hoffe nun kann man mich verstehen. Und wegen den Satzzeichen ich dachte eigentlich es wären genügend da, achja ich liebe verschachtelte Sätze :D.


  • Administrator

    Xebov schrieb:

    So ich hoffe nun kann man mich verstehen.

    Ich zweifle langsam an mir selber. Ich versteh den Inhalt deiner Sätze einfach nicht ...

    Ich nehme mal einfach dein ursprünglicher Satz, welcher sich auf Simon2s Aussage gleich vor deinem Beitrag bezog und stelle dazu Fragen. Zudem füge ich fett hervorgehoben ein paar Korrekturen, bzw. Satzzeichen, ein. Nur damit ich sehe, ob ich die Sätze auch richtig verstehe 🙂

    Xebov schrieb:

    Ich glaube**,** er bezog sich dabei eher auf die Destruktoren**,** die vorhanden sind. Wobei Speicher freigeben**,** der mit new erzeugt wurde**,** ja ansich auch geht**.** Man könnte ihn in void* lagern und dann freigeben, das wäre zwar nicht ganz korrekt**,** würde doch aber eigentlich nen Teil des Lecks verhindern?

    • Was sind Destruktoren, welche vorhanden sind? Jede Klasse in C++ hat automatisch auch einen Destruktor.
    • Ja, man kann eine Speicheradresse in void* speichern. Aber wie willst du den Speicher dann freigeben? Ein delete auf einen void -Zeiger geht nicht. Ein free aus der C Bibliothek ruft undefiniertes Verhalten hervor.
    • Simon2 hat ja nicht gesagt, dass ein OS kein Speicher freigeben kann. Er hat gesagt, dass keine Destruktoren aufgerufen werden. Dazwischen gibt es einen grossen Unterschied.

    Grüssli 😕

    PS: Ich bin kein Rechtschreib- oder Grammatikfanatiker. Ich mache auch viele Fehler, aber bei dir ist das schon ... naja 🙂



  • Xebov schrieb:

    ...Wenn ich mit new etwas erzeuge wäre ein Destruktor nicht automatisch vorhanden ...

    😕 Der Destruktor ist Bestandteil der Klassendefinition....
    seine Existenz hat mit der Art, wie ein Objekt dieser Klasse erzeugt wird, nichts zu tun.

    Sag doch einfach: "Ich habe mich falsch ausgedrückt. Was ich wirklich meinte war <xyz>".
    Oder noch besser: "Ich weiß auch nicht, was daersc gemeint hat." (denn eigentlich ging es um seinen Kommentar, das OS riefe selbständig Destruktoren auf)

    ...und bitte nicht als "o ich glaub da hab ich irgendwie aber ihr wisst ja schon falsch oder so destruktor gemeinte Sache genannt aber ist ja alles ganz anders..." 😉

    Auch ich bin kein Orthographie- oder Grammatikfanatiker, aber es gibt EINE (einfach einzuhaltende) Regel, deren Einhaltung Lesen und Verstehen um den Faktor 1000 vereinfacht (bzw. tw. erst ermöglicht):
    Sätze durch Satzzeichen trennen!!
    (Auch und gerade Nebensätze! Dafür hat der liebe Gott Kommata erfunden).

    Wenn Du Dir dann noch angewöhnst, nicht beliebig "Füllsel" ("so", "mein ich", "ja", ...) reinzuwerfen, dann werden alle hier NOCH motivierter sein, Dein Anliegen zu verstehen und zu unterstützen. 😃

    Gruß,

    Simon2.



  • Dravere schrieb:

    Ich zweifle langsam an mir selber. Ich versteh den Inhalt deiner Sätze einfach nicht ...

    Also ich hab da keine Probleme, mag die machtd er Gewohnheit sein.

    [quote="Dravere"]

    • Was sind Destruktoren, welche vorhanden sind? Jede Klasse in C++ hat automatisch auch einen Destruktor.
    • Ja, man kann eine Speicheradresse in void* speichern. Aber wie willst du den Speicher dann freigeben? Ein delete auf einen void -Zeiger geht nicht. Ein free aus der C Bibliothek ruft undefiniertes Verhalten hervor.
    • Simon2 hat ja nicht gesagt, dass ein OS kein Speicher freigeben kann. Er hat gesagt, dass keine Destruktoren aufgerufen werden. Dazwischen gibt es einen grossen Unterschied.

    1. ja natürlich hat sie das aber für den Automatischen aufruf existiert er nur wenn das Objekt nicht per new angelegt wurde denn solche Objekte werden ja nicht automatisch zerstört sondenr nur per delete damit existeriert er zwar durch die deffinition da aber existiert für das Programm selbst nicht da es ja über keine Möglichkeit verfügt das Objekt automatisch selbst zu löschen
    2. damit beschäftige ich mich nich, das war nur ein Gedankenanstoß
    3. Das hab ich ja auch nie behauptet, ich war nur der Meinung er hatte den Post auf den er sich bezog falsch verstanden.

    Dravere schrieb:

    PS: Ich bin kein Rechtschreib- oder Grammatikfanatiker. Ich mache auch viele Fehler, aber bei dir ist das schon ... naja 🙂

    Ja ich weis, ist nix neues, ich gebs auch erstmal auf, ich glaube nämlich das wir hier schon ähnliches Meinen aber uns irgendwie nicht ganz verstehen.



  • Xebov schrieb:

    Also ich hab da keine Probleme, mag die machtd er Gewohnheit sein.

    Die Aussage des Tages.

    1. ja**,** natürlich hat sie das**.** Aber für den Automatischen aufruf existiert er nur**,** wenn das Objekt nicht per new angelegt wurde**.** Denn solche Objekte werden ja nicht automatisch zerstört sondenr nur per delete**.**

    Das ist quatsch. Gerade Objekte, die automatisch erzeugt werden, werden auch automatisch zerstört.

    Damit existeriert er zwar durch die deffinition [da], aber [existiert] für das Programm selbst nicht**,** da es ja über keine Möglichkeit verfügt das Objekt automatisch selbst zu löschen

    Siehe oben.

    ich glaube nämlich das wir hier schon ähnliches Meinen aber uns irgendwie nicht ganz verstehen.

    Wundert Dich das? Beziehungsweise, merkst Du wie die oben eingestreuten Kommas und Punkte (die Großschreibung habe ich schon nur nach dem Punkt betrachtet) die Lesbarkeit steigern?


  • Administrator

    Xebov schrieb:

    Also ich hab da keine Probleme, mag die machtd er Gewohnheit sein.

    Dass du deine Sätze verstehst, erstaunt mich nicht. Du weisst ja auch, was du sagen willst, hoffe ich zumindest 😃

    Xebov schrieb:

    1. ja natürlich hat sie das aber für den Automatischen aufruf existiert er nur wenn das Objekt nicht per new angelegt wurde denn solche Objekte werden ja nicht automatisch zerstört sondenr nur per delete damit existeriert er zwar durch die deffinition da aber existiert für das Programm selbst nicht da es ja über keine Möglichkeit verfügt das Objekt automatisch selbst zu löschen

    Die Dinger sind aber trotzdem vorhanden und existieren auch. Sie werden einfach nicht für das entsprechende Objekt aufgerufen, wenn man eben dieses per new angelegt hat.
    Aber ich verstehe nicht so recht, was du damit sagen wolltest. Simon2 hat ja auch nichts anderes behauptet.

    Xebov schrieb:

    2. damit beschäftige ich mich nich, das war nur ein Gedankenanstoß

    Anstoss wofür? Worauf wolltest du hinaus?

    Xebov schrieb:

    3. Das hab ich ja auch nie behauptet, ich war nur der Meinung er hatte den Post auf den er sich bezog falsch verstanden.

    Inwiefern soll er ihn falsch verstanden haben?

    Xebov schrieb:

    Ja ich weis, ist nix neues, ich gebs auch erstmal auf, ich glaube nämlich das wir hier schon ähnliches Meinen aber uns irgendwie nicht ganz verstehen.

    Bitte nicht aufgeben, wir kriegen das noch hin, ich streng mich auch an 🙂
    Bin irgendwie wahnsinnig neugierig darauf, was es am Ende war. Das ist wie ein Weihnachtsgeschenk, welches man einfach nicht aufkriegt 😃

    Grüssli


Log in to reply