v.push_back(*(new obj)); // was passiert hier?



  • Hallo!
    Was passiert hier?

    #include <vector>
    #include <iostream>
    
    class obj {
    private:
    	int b;
    public:
    	obj(int b) {
    		this->b=b;
    	}
    	int getb() {
    		return b;
    	}
    
    	~obj() {
    		std::cout << "destructor" << std::endl;
    	}
    };
    
    int main() {
    	std::vector<obj> v;
    	v.push_back(*(new obj(2)));
    	v.push_back(*(new obj(4)));
    	v.push_back(*(new obj(6)));
    	v.push_back(*(new obj(8)));
    	v.push_back(*(new obj(2)));
    	v.push_back(*(new obj(5)));
    
    	for(unsigned int i=0; i < v.size(); i++) {
    		std::cout << v[i].getb() << std::endl;
    	}
    	return 0;
    }
    

    Die Ausgabe lautet:

    destructor
    destructor
    destructor
    destructor
    destructor
    destructor
    destructor
    2
    4
    6
    8
    2
    5
    destructor
    destructor
    destructor
    destructor
    destructor
    destructor
    

    1. Wieso werden die Objekte gleich wieder zerstört (Destruktor-Aufruf)?
    2. Wieso sind sie trotzdem ansprechbar?
    3. Wird der Speicher freigegeben (new, aber kein delete...Destruktor wird aber ja aufgerufen)?

    Ich danke euch!



  • Was du da treibst, ist Schwachsinn.



  • Die Zeile

    v.push_back(*(new obj(2)));
    

    ist eigentlich genau das Selbe wie

    v.push_back(obj(2));
    

    Es passiert folgendes
    1.
    Ein neues Objekt wird angelegt
    2.
    Die Funktion push_back wird mit diesem Objekt als Argument aufgerufen und da der Input-Parameter keine Referenz ist, wird es kopiert (CopyConstructor wird aufgerufen). Das ganze kannst du ja mal überprüfen, indem du für obj den Copy-Constructor überlädst.
    3.
    Das in 1. angelegte Objekt wird zerstört weil es den Scope verlässt und das von push_back kopierte Objekt wird gespeichert
    4.
    Dein Programm ist zu ende und der vector wird zerstört und damit auch alle gespeicherten Inhalte, d.h. ~vector wird aufgerufen, der für jedes element ~obj aufruft.

    Hoffe das war verständlich.

    Schönen Gruß

    Max



  • Gnawr schrieb:

    Was passiert hier?

    new obj(2) alloziert auf dem Freispeicher ein neues Objekt.

    Dann übergibst du dieses Objekt per Referenz an push_back. Dieses erzeugt über den Kopierkonstruktor eine Instanz von obj innerhalb des Vektors. Der von new erhaltene Zeiger geht verloren. Am Ende wird der Vektor mitsamt allen enthaltenen Objekten zerstört.
    Zwischendurch wird der Vektor ein paar mal vergrößert, dabei werden die Objekte umkopiert und natürlich auch zerstört.
    Gib dir mal noch den Konstruktor und den Kopierkonstruktor aus, dann wird es ein bisschen klarer.
    Ach ja, ich hab es nicht explizit erwähnt, aber du erzeugst natürlich Speicherlecks mit deinem new-ohne-delete.



  • Max3000 schrieb:

    Die Zeile

    v.push_back(*(new obj(2)));
    

    ist eigentlich genau das Selbe wie

    v.push_back(obj(2));
    

    Eben nicht! Der Speicher wird zu Ende des Programms vom Betriebssystem weggeräumt, nicht von vector. Zeiger werden in Smartpointern gespeichert, und sonst normalerweise in gar nichts!



  • Gnawr schrieb:

    Was passiert hier?

    std::vector<obj> v;
    	v.push_back(*(new obj(2)));
    	v.push_back(*(new obj(4)));
    	v.push_back(*(new obj(6)));
    	v.push_back(*(new obj(8)));
    	v.push_back(*(new obj(2)));
    	v.push_back(*(new obj(5)));
    
    	for(unsigned int i=0; i < v.size(); i++) {
    		std::cout << v[i].getb() << std::endl;
    	}
    	return 0;
    

    Die Ausgabe lautet:

    destructor
    destructor
    destructor
    destructor
    destructor
    destructor
    destructor
    2
    4
    6
    8
    2
    5
    destructor
    destructor
    destructor
    destructor
    destructor
    destructor
    

    1. Wieso werden die Objekte gleich wieder zerstört (Destruktor-Aufruf)?

    Welche Objekte? Wenn Du die meinst, die Du im Freispeicher erzeugt hast, die hängen da immernoch (Speicherleck). Aber der Vektor vergrößert sich nach und nach und muss ggf Elemente in einen größeren Puffer umkopieren. Da werden dann auch welche zerstört. Du kannst das vielleicht besser nachvollziehen, wenn Du dem Kopierkonstruktor auch eine solche Ausgabe spendierst.

    2. Wieso sind sie trotzdem ansprechbar?

    Sind sie nicht. Das sind andere Objekte. Bau Dir mal einen sprechenden Kopierkonstruktor.

    3. Wird der Speicher freigegeben (new, aber kein delete...Destruktor wird aber ja aufgerufen)?

    Speicherleck. Und Du bist Schuld. :-p

    kk



  • Ok Leute, danke...das hilft mir schon mal weiter!

    Zum Sinn und Unsinn: Natürlich ging es mir bei diesem Beispiel nur darum, die Abläufe genauer nachzuvollziehen. Das dieser Code nicht wirklich sinnvoll ist, ist schon klar 🙂

    🙂



  • 314159265358979 schrieb:

    Zeiger werden in Smartpointern gespeichert, und sonst normalerweise in gar nichts!

    So ein Bullshit.



  • knivil schrieb:

    314159265358979 schrieb:

    Zeiger werden in Smartpointern gespeichert, und sonst normalerweise in gar nichts!

    So ein Bullshit.

    Du bist auch bullshit.



  • 314159265358979 schrieb:

    knivil schrieb:

    ...So ein Bullshit.

    Du bist auch bullshit.

    Schau an: Jeder Mensch kann Scheiße produzieren.
    Welche Überraschung!

    Gruß,

    Simon2. 😉



  • 314159265358979 schrieb:

    knivil schrieb:

    314159265358979 schrieb:

    Zeiger werden in Smartpointern gespeichert, und sonst normalerweise in gar nichts!

    So ein Bullshit.

    Du bist auch bullshit.

    Auch wenn bullshit etwas hart ist - im Prinzip hat knivil Recht.
    Und da brauchen wir nicht auf dieses Niveau runterfallen...

    Rohe Zeiger machen durchaus Sinn. Man muss nicht alles in Smartpointer packen. idR sind Smartpointer für besitzende Zeiger die beste Wahl, aber jede Regel hat Ausnahmen. Wenn man zB besitzende Zeiger in einen Container packen will und der Container soll die Objekte verwalten -> boost::ptr_xxx und kein xxx<shared_ptr<>>.

    Rohe Zeiger sind mit Vorsicht zu genießen, aber nicht zu verdammen 🙂


Anmelden zum Antworten