Operationen mit mehreren Klassen


  • Mod

    vatan89 schrieb:

    KX   //Durch das X x [2][1] wird das KX zweimal ausgegeben 
    KX   //
    KY   //Anschließend tritt der Konstruktor von Class Y 
    KX   //und von der Class X
    DX   // Destruktor von Class X 
    DY   //Weshalb kommt hier erst der Destruktor von Y ? 
    DX   // ICh schätze mal die beiden DX killen die beiden KX am Anfang 
    DX
    KX   // hier beginnt die Instanz der Klasse X x ? 
    KX
    KY
    KX   // Ende von der Instanz Xx ? 
    KZ   
    KX   
    KX
    KY
    KX   // gleiche Frage wie oben. Warum kommt hier nochmal der Konstruktor von X
    KZ
    

    Aufräumen geschieht genau umgekehrt wie das Erstellen.

    int main()
    {
      {
        Y y;
    

    Ein Y wird erstellt. Es enthält 2 X. Als Member werden diese zuerst erstellt:

    KX
    KX
    

    Dann der Rest vom Y selbst:

    KY
    
    X x;
    

    Ein X wird erstellt:

    KX
    
    }
    

    Ende des Scopes, das Y und das X werden zerstört. Zuerst das X:

    DX
    

    Dann das Y:

    DY
    

    Dann die beiden X, die Member von Y sind:

    DX
    DX
    
    Z*ZPtr= new Z [2];
    

    Zwei Z werden erzeugt. Nacheinander. Jedes Z enthält ein Y und ein X (das Y zuerst, da es weiter oben steht). Das Y wieder zwei X. Also zuerst wird das Y erzeugt, dazu werden zuerst zwei X erzeugt:

    KX
    KX
    

    Dann das Y selbst:

    KY
    

    Dann das X als zweiter Member des Z:

    KX
    

    Dann das Z selbst:

    KZ
    

    ann das gleiche noch einmal für das zweite Z:

    KX
    KX
    KY
    KX
    KZ
    

    Preisfrage, ob du es auch verstanden hast: Wie sähe die Ausgabe bei einem anschließenden delete[] ZPtr; aus? (Mit Erklärung, nicht einfach ausprobieren!)



  • poah Wahnsinn danke Leute, echt. Hab's jetzt endlich kapiert *schwere Geburt* 🙂

    Also zur Preisfrage:

    Wenn ich den Pointer Kille :

    DZ
    DX
    DY
    DX
    DX
    DZ
    DX
    DY
    DX
    DX
    

    ???? so in der Art



  • Fast. y wird in Z zuerst deklariert, also auch zuerst zerstört.
    Tauscch die Zerstörung von y und x aus, dann stimmt's.


  • Mod

    Ethon schrieb:

    Fast. y wird in Z zuerst deklariert, also auch zuerst zerstört.
    Tauscch die Zerstörung von y und x aus, dann stimmt's.

    Nein, gerade aus diesem Grund ist es so wie vatan89 richtig gesagt hat.



  • Ethon schrieb:

    Fast. y wird in Z zuerst deklariert, also auch zuerst zerstört.

    zuletzt zerstört.
    Zerstört wird immer in der umgekehrten Reihenfolge wie aufgebaut wurde.



  • Grrr, in letzter Zeit häufen sich Griffe ins Klo bei mir. Vor allem wenn ich eigentlich wüsste wie es richtig ist.
    Ich schiebe es mal auf Müdigkeit beim Erstellen des Posts und entschuldige mich für eventuell entstandene Verwirrung. 😉



  • Leute hab grad die Klausur hinter mir und dazu eine dringende Frage, was ich unbedingt wissen muss:

    In der Aufgabe kam sowas ähnliches wie ich hier schon gepostet habe.

    es sah in der Form aus, solang es noch frisch ist:

    3- Klassen jeweils x,y,z

    f1(....)
    { Z = new y} // oder so ähnlich, aufjedenfall ein new Objekt

    int main () 
    {
     Y y;  // so in der Form die Funktion f1 wurde in der Klasse beschrieben
     f1(y); 
    
    }
    

    Meine Frage, befindet sich das f1(y) noch im Scope ? sprich wenn ich die Konstruktoren erzeuge.

    KX   |
    KX   | gehören alle dem Objekt Yy
    KY   |
    KX   |
    

    werden diese vor dem übergang zu f1(y) zerstört oder erst nach der ausführung des von f1(y) bzw des new y ?

    falls ich es etwas unklar formuliert habe, entschuldigt dies bitte es ist nur eine wage beschreiben. Ich hatte eine wahl zwischen

    KX             KX
    KX             KX
    KY             KY
    KX             KX
    KZ    oder     KZ
    KX             DZ            
    KX             DX
    KY             DY
    KX             DX
    KZ             DX
    DZ             KX
    DX             KX
    DY             KY         
    DX             KX
    DX             KZ
    

    ich habe dummerweise das linke gewählt, weil ich dachte, dass zuerst new noch erstellt wird und dann das objekt von oben zerstört wird. Aber ich denke dass das rechte richtig ist.

    Findet nacht der main die zerstörung vor dem new statt oder erst nachdem new erstellt wurde ?



  • Der Scope endet mit der schließenden Klammer. Zu dem Zeitpunkt werden auch die lokalen Variablen zerstört.

    Eine Funktion hat ihren eigenen Scope. Du kannst es dir so vorstellen, dass der Rumpf der Funktion an der Stelle des Aufrufs eingefügt wird (was bei inline-Methoden tatsächlich der Fall ist)

    Also sind bezüglich der Objekt-Lebensdauer äquivalent:

    f()
    {
      X x = new X;
    }
    
    int main()
    {
      Y y;
    
      f();
    
    }
    

    und

    int main()
    {
      Y y;
    
      {
        X* x = new X;
      }
    
    }
    

    Da das innere x aber nicht zerstört wird, ist es eigentlich auch egal, wie lange es genau lebt 😉


  • Mod

    Ein Scope wird verlassen, wenn seine geschweifte Klammer geschlossen wird:

    {
     Y y;
     // Code
     {
       // Code
      {
       // usw.
    
      } // interessiert y nicht die Bohne
      // Code
     } // interessiert y nicht die Bohne
     // Code
    
    } // Hier stirbt y.
    

    Dazwischen mag stehen was will. Selbstverständlich auch Funktionsaufrufe. Auch bei einer Exception würde y erst an der beschriebenen Stelle zerstört. Ebenso bei einem goto, break oder ähnlichem aus dem Scope heraus. Einzig solch gefürchtete Mittel wie exit, abort, longjmp & Co. können den Scope verlassen, ohne dass ein Destruktor aufgerufen wird (und sind daher zu vermeiden, wenn man nicht ganz genau weiß, was man tut).

    daddy_felix schrieb:

    int main()
    {
      Y y;
      
      {
        X* x = new X;
      }
     
    }
    

    Da das innere x aber nicht zerstört wird, ist es eigentlich auch egal, wie lange es genau lebt 😉

    Das x wird schon zerstört. Aber x ist hier ein roher Pointer und sein Pointee bekommt davon nichts mit. Das mit new erzeugte Objekt existiert also immer noch und ist nicht mehr erreichbar. Typisches Anfängerspeicherloch, wie bei bisher jedem Code den vatan89 uns von seinem Lehrer gezeigt hat.



  • also ist die rechte Variante richtig ? Da lag ich mit der linken wohl wieder voll auf dem Holzweg...wo soll das nur enden mit mir


  • Mod

    vatan89 schrieb:

    also ist die rechte Variante richtig ?

    Nein, alles ist falsch. Oder wahrscheinlicher: Du erinnerst dich falsch an die Aufgabenstellung.



  • SeppJ schrieb:

    Typisches Anfängerspeicherloch, wie bei bisher jedem Code den vatan89 uns von seinem Lehrer gezeigt hat.

    Wobei ich das in diesem Fall durchaus für Absicht halte. Es geht darum, zu erkennen, wann (und ob) Destruktoren aufgerufen werden. Da ist so ein einzelnes new natürlich ein fieser Trick.

    Wesentlich interessanter (und realitätsnäher) wäre die Aufgabe natürlich mit Smart Pointern 😉



  • ja ich habe ein sehr schlechtes Gedächtnis :S

    aber in dem moment kam es mir halt logisch vor dass die destruktoren von

    Y y;

    erst nach der Ausführung von

    f1(new) kommen. Weil die sich ja in der gleichen Klammer befinden {} kein plan



  • vatan89 schrieb:

    aber in dem moment kam es mir halt logisch vor dass die destruktoren von

    Y y;

    erst nach der Ausführung von

    f1(new) kommen.

    ist ja auch richtig so. Was wäre sonst mit diesem Code:

    {
      Y y;
    
      f();
    
      y.DoSomething();
    }
    


  • wenn das richtig ist gibts erstmal Freibier von mir auf dem Campus


Anmelden zum Antworten