Seite 1 von 1

Dekonstruktor wird Automatisch bei Vector aufgerufen?

Verfasst: 19.12.2011, 03:58
von Raidenkk
Hey,
ich erstelle mit dem Folgenden Befehl eine Instanz von meiner Flasche:

vBottles.push_back (CBottles ());

Sobald ich eine Instanz erstelle reagiert logischerweise der Konstruktor von der Flasche.
Was mir aber Spanisch vorkommt warum auch der Dekonstruktor anschlägt obwohl die Flasche nicht gelöscht wurde.
Optisch ist die Flasche wahrnehmbar und mit der Flasche interagieren kann ich auch also denke ich mal das sie auch nicht gelöscht wurde.
Jetzt stellt sich die Frage wie ist sowas möglich und vor allem ist das Normal oder nicht wenn man eine Flasche mit dem Vector Spawnt das der Dekonstuktor Alarm schlägt?

EDIT:
Ich habe mal 3 Flaschen erstellt und es kommt folgendes in meiner Konsole zum Vorschein:
Bild

Gelöscht wurde aber keine Flasche sie stehen alle 3 samt auf dem Tisch.

Re: Dekonstruktor wird Automatisch bei Vector aufgerufen?

Verfasst: 19.12.2011, 06:40
von gdsWizard
Hallo,


Du erzeugst das Objekt auf dem Stack. Außerdem "lebt" das Objekt nur für den Funktionsaufruf push_back(). Die Destruktoraufrufe sind also korrekt.

Wenn ein Objekt in einem Funktionsaufruf erzeugt wird, dann wird es nach dem Funktionsaufruf auch wieder automatisch zerstört. In dem Screenshot kannst Du gut sehen wie das funktioniert. Da du das Objekt in den Vektor einträgst kann ein ungültiges Objekt eingetragen sein. Das hängt von deiner Vektorklasse ab, ob Sie eine Kopie speichert oder die Reference. Wenn Sie eine Kopie macht dann von einer gültigen CBottles. Sollte die Vektorklasse eine Reference speichern dann ist sie nicht gültig !

Wenn deine Vektorklasse Referenzen speichert solltest du das Objekt mit new erzeugen oder aber das Objekt extra als normale Variable erzeugen:

CBottles a;

vBottles.push_back (a);

Re: Dekonstruktor wird Automatisch bei Vector aufgerufen?

Verfasst: 19.12.2011, 06:57
von Raidenkk
Ahh da bin ich ja beruhigt und hat auch sinn, ich dachte schon mir ist mal wieder ein Fehler durch die Hand geflossen :)

EDIT:
Ich sollte wirklich auf die Schreibweise im Buch achten schon das 2 mal das ich etwas falsch aufgenommen habe :D

NR1. Dekonstruktor = Destruktor
NR2. Objektorisiert = Objektorientiert

Danke vielmals :)

Re: Dekonstruktor wird Automatisch bei Vector aufgerufen?

Verfasst: 19.12.2011, 09:34
von IlikeMyLife
Ist es nicht sinniger, solche Instanzen auf dem Heap zu erzeugen und diese als Pointer beziehungsweise als Referenz zu übergeben?

Re: Dekonstruktor wird Automatisch bei Vector aufgerufen?

Verfasst: 19.12.2011, 10:34
von Schrompf
Nein, ist es nicht unbedingt.

Vergleich im Detail:

Code: Alles auswählen

some_vector.push_back( Object());
- temporäres anonymes Objekt wird auf dem Stack konstruiert: Konstruktor plus ein paar Takte für den Platz auf dem Stack.
- Objekt im Array wird mittels Kopierkonstruktor als Kopie des temporären Objekts erzeugt: Kopierkonstruktor
- temporäres anonymes Objekt wird zerstört: Destruktor

im Vergleich zu:

Code: Alles auswählen

some_vector.push_back( new Object());
- new allokiert Platz auf dem Heap für das Objekt: mehrere tausend Takte.
- Konstruktor
- Zeiger wird im Array gespeichert: ein paar Takte

Theoretisch passiert also weniger, wenn man per new allokiert. Da hast Du also Recht. Jedoch ist new (und das delete dazu) viele hundert Mal teurer als ein Kopierkonstruktor oder Destruktor eines *einfachen* Objekts, so dass es sich für die meisten Objekte lohnt, sie direkt zu speichern.

Unter C++0x mit RValue-Referenzen sieht es sogar noch schlechter aus für die new-Lösung: da wird im Beispiel oben (zweite Zeile) der RValue-Konstruktor benutzt, wodurch auch komplexe Objekte mit Strings oder Containern drin nahezu kostenlos kopierbar sind.

Zusammenfassung: man sollte auch hier nur dann Objekte auf dem Heap konstruieren, wenn man es unter anderen Umständen auch tun würde: komplexe Besitzer-Verhältnisse, Lebensdauer-Steuerung. Aus Performance-Sicht macht man mit new eigentlich nahezu immer Miese. Ganz zu schweigen davon, dass man sich mit new auch die manuelle Zerstörung des Objekts aufhalst, was eine gängige Fehlerquelle ist. Und unnötige Arbeit, da C++ mit dem Destruktor eine so elegante und bequeme Lösung für die meisten Resourcen-Probleme hat.

Re: Dekonstruktor wird Automatisch bei Vector aufgerufen?

Verfasst: 19.12.2011, 11:13
von kimmi
Aber darauf achten, dass Copy-Konstruktor sowie ein Assignment- und Equal-Operator da sind. Genaueres dazu findest du hier:http://en.wikipedia.org/wiki/Copy_constructor

Gruß Kimmi

Re: Dekonstruktor wird Automatisch bei Vector aufgerufen?

Verfasst: 19.12.2011, 11:15
von IlikeMyLife
C++ bietet hierzu die möglichkeit eines auto-pointers an.

http://www.cplusplus.com/reference/std/memory/auto_ptr/

diese Variante nutze ich teils sehr gerne um die Fehleranfälligkeit von delete zu umgehen.
Ist allerdings nur eine wage beurteilung meiner seits, da ich dieses selbst erst seid kurzem verwende.

Re: Dekonstruktor wird Automatisch bei Vector aufgerufen?

Verfasst: 19.12.2011, 11:23
von kaiserludi
Ein guter Compiler optimiert dir die Kopie auch weg und verwendet stattdessen das Originalobjekt in der Funktion, wenn er merkt, dass du eh nirgends sonst drauf zugreifst. Das spart dir im Release-Mode dann sowahl new als auch Kopie und kann situationsabhängig sogar etwas schneller als eine Referenz auf ein loakles Stackobjejkt sein. Das hat Krishty hier letztens mal näher ausgeführt.

Re: Dekonstruktor wird Automatisch bei Vector aufgerufen?

Verfasst: 19.12.2011, 11:37
von Schrompf
kimmi hat geschrieben:Aber darauf achten, dass Copy-Konstruktor sowie ein Assignment- und Equal-Operator da sind. Genaueres dazu findest du hier:http://en.wikipedia.org/wiki/Copy_constructor
Nein, das kann man so allgemein nicht sagen. Der Compiler erzeugt Kopier-Konstruktor und Zuweisungsoperator, wenn sie fehlen. Und das ist eigentlich immer vorzuziehen, außer man muss eigene Logik ausführen. Aber wenn man obigen Leitsatz (kein new, wenn nicht notwendig) beachtet, bekommt man auch Strukturen und Klassen, für die die automatisch generierten Operatoren völlig ausreichen.

Der Zuweisungsoperator ist ein anderes Blatt. Der wird nicht automatisch vom Compiler erzeugt. Man braucht ihn allerdings auch nicht, wenn man ein Objekt in einen Vector packen will. Der wird erst wichtig, wenn man die STD-Algorithmen verwenden will oder die Klasse als Key für manche Container benutzen will.

Übrigens verursacht auch ein auto_ptr ein new und delete. Man erspart sich damit die Arbeit, manuell das Objekt zu zerstören, ist aber in Sachen Performance noch schlechter als mit manuellem new/delete.

Re: Dekonstruktor wird Automatisch bei Vector aufgerufen?

Verfasst: 19.12.2011, 11:41
von IlikeMyLife
@ Schrompf:
dann mal vielen dank für die information was den auto_ptr betrifft. derzeit fällt es bei mir noch nicht so ins gewicht bei meinem umfang des projektes. später hätte ich mich allerdings gefragt, wo ich die performance her bekomme

Re: Dekonstruktor wird Automatisch bei Vector aufgerufen?

Verfasst: 19.12.2011, 11:49
von Schrompf
Och, das passt schon! Auch von new/delete kannst Du einige Millionen pro Sekunde machen. Es ist halt nur (bei schlichten Objekten) um Zehnerpotenzen langsamer als ein Objekt auf dem Stack. Daher wollte ich die ursprüngliche Empfehlung für new nicht unkommentiert stehen lassen.

Re: Dekonstruktor wird Automatisch bei Vector aufgerufen?

Verfasst: 19.12.2011, 11:52
von kaiserludi
Schrompf hat geschrieben: Der Compiler erzeugt [...] Zuweisungsoperator, wenn sie fehlen.
[...]
Der Zuweisungsoperator ist ein anderes Blatt. Der wird nicht automatisch vom Compiler erzeugt.
Ich bezweifle mal, dass das so stimmt ;)
IlikeMyLife hat geschrieben:@ Schrompf:
dann mal vielen dank für die information was den auto_ptr betrifft. derzeit fällt es bei mir noch nicht so ins gewicht bei meinem umfang des projektes. später hätte ich mich allerdings gefragt, wo ich die performance her bekomme
Das hat Null mit der Projektgröße zu tun. Du musst nicht bei großen Projekten vermehrt auf Performance achten im Verlgeich zu kleinen. Du musst bei den kleinen Teilen eines Programmes drauf achten, welche besonders viel von der gesamten Ausführungszeit fressen: In der Regel sind das Codeabschnitte, die sehr sehr häufig ausgeführt werden und meist ziemlich low-level sind.Es bringt um 1.000 mal mehr, etwas zu optimieren, was 1µs dauert und 10 Millionen mal ausgeführt wird, als etwas, was 10ms dauert, aber nur einmal im Programm ausgeführt wird.

Re: Dekonstruktor wird Automatisch bei Vector aufgerufen?

Verfasst: 19.12.2011, 11:55
von kimmi
Schrompf hat geschrieben:
kimmi hat geschrieben:Aber darauf achten, dass Copy-Konstruktor sowie ein Assignment- und Equal-Operator da sind. Genaueres dazu findest du hier:http://en.wikipedia.org/wiki/Copy_constructor
Nein, das kann man so allgemein nicht sagen. Der Compiler erzeugt Kopier-Konstruktor und Zuweisungsoperator, wenn sie fehlen. Und das ist eigentlich immer vorzuziehen, außer man muss eigene Logik ausführen. Aber wenn man obigen Leitsatz (kein new, wenn nicht notwendig) beachtet, bekommt man auch Strukturen und Klassen, für die die automatisch generierten Operatoren völlig ausreichen.
...
Das stimmt aber nur dann, wenn man wirklich komplett auf Pointer und new verzichtet hat. Irgendwie bezweifle ich das hier und deswegen warne ich lieber und weise auf entsprechende Doku hin. Weil dann wird das Problem hoffentlich in der Tiefe verstanden, was gerade an einer kitzligen Setlle wie hier sicher nicht schaden kann :).

Und wenn man einen alten Compiler benutzen muß, kann man leider nicht immer auf modernere Features vertrauen. Da spreche ich aus leidvoller Erfahrung, weil der Prozess, hier einen neuen Compiler einzuführen, komplexer ist als den Code neuzuschreiben.

Gruß Kimmi

Re: Dekonstruktor wird Automatisch bei Vector aufgerufen?

Verfasst: 19.12.2011, 11:57
von Schrompf
kaiserludi hat geschrieben:
Schrompf hat geschrieben: Der Compiler erzeugt [...] Zuweisungsoperator, wenn sie fehlen.
[...]
Der Zuweisungsoperator ist ein anderes Blatt. Der wird nicht automatisch vom Compiler erzeugt.
Ich bezweifle mal, dass das so stimmt ;)
Oh, da habe ich mich vertippt. Ich wollte auf den Vergleichsoperator (Equal Operator in Kimmis Beitrag) Bezug nehmen. Danke für den Hinweis!

@Kimmi: stimmt schon. Mir war es halt wichtig, dass ein evtl. Mitlesender nicht überall die Operatoren selbst implementiert, weil er denkt, dass das so sein muss. Compiler-generierter Code ist eigentlich immer dem manuellen vorzuziehen, solange er den Job erledigt.

Re: Dekonstruktor wird Automatisch bei Vector aufgerufen?

Verfasst: 19.12.2011, 11:59
von kimmi
Zustimmung, sehe ich auch so. Aber ich habe auch schon ollen Code um Faktoren schneller gemacht, weil ein Autor zuviel kopiert hatte :). Das kann halt auch mal passieren. Leider leben wir in keiner perfekten Welt.

Gruß Kimmi

Re: Dekonstruktor wird Automatisch bei Vector aufgerufen?

Verfasst: 19.12.2011, 12:17
von dot
Was die Performance der Variante mit new angeht, sollte man auch noch bedenken, dass die eigentlichen Objekte dort irgendwo im Speicher rumliegen und jeder Zugriff über einen Pointer erfolgen muss (zusätzliche Indirektion).

Weil auto_ptr erwähnt wurde: Richig verwendet sollte auto_ptr praktisch keinen Overhead im Vergleich zur "manuellen" benutzung von new/delete haben. Generell sollte man eigentlich auf Smartpointer/RAII setzen, wenn man nicht irgendeinen extrem guten Grund hat es nicht zu tun. Denn ohne ist es praktisch unmöglich Code wirklich exceptionsafe zu halten.
Was auto_ptr angeht ist noch wichtig zu wissen, dass man um keinen Preis der Welt auto_ptr in einen std:: Container packen darf, auch wenn es vielleicht auf den ersten Blick wie eine gute Idee aussieht.
Allerdings ist auto_ptr auch deprecated. Heutzutage sollte man auf auto_ptr verzichten und besser unique_ptr benutzen, das ersetzt auto_ptr vollständig und ist in jeder Hinsicht überlegen. unique_ptr kann man auch in std:: Container packen.

Re: Dekonstruktor wird Automatisch bei Vector aufgerufen?

Verfasst: 20.12.2011, 08:53
von IlikeMyLife
Ich habe mich gestern nachmittag viel mit meinem DirectX11-Framework beschäftigt, an dem ich tüftle...
in diesem Zuge habe ich zu dem auto_ptr noch eine Bemerkung zu machen. Es mag zwar Stimmen, dass ein auto_ptr mehr an kosten hat, als new und delete, dazu habe ich noch in erfahrung bringen können, dass sich der auto_ptr scheinbar um fehlerbehandlungen kümmert.

EDIT:
@ dot: habe deinen Kommentar zum unique_ptr erst später gelesen als ich diesen post geschrieben habe :-)

EDIT2:
Grade gefunden:
http://www.humbug.in/stackoverflow/de/s ... 51099.html
Hinweis: lest die englische und nicht die deutsche Version. Ist doch sehr verwirrend die Übersetzung ;-)

Re: Dekonstruktor wird Automatisch bei Vector aufgerufen?

Verfasst: 20.12.2011, 11:45
von Artificial Mind
Okay diese deutsche Übersetzung ist echt der Hammer :D vielen Dank für die beste std::-Übersetzung die ich je gesehen habe.

Re: Dekonstruktor wird Automatisch bei Vector aufgerufen?

Verfasst: 20.12.2011, 13:06
von joggel
In welcher Welt wird denn "std::" als "Geschlechtskrankheit" übersetzt?
Ich bin verwirrt :D

Re: Dekonstruktor wird Automatisch bei Vector aufgerufen?

Verfasst: 20.12.2011, 13:11
von Artificial Mind

Re: Dekonstruktor wird Automatisch bei Vector aufgerufen?

Verfasst: 20.12.2011, 13:13
von joggel
Aahhh, okay! Das erklärt es :)
[Edit]
Also, ist trotzdem ein erstes Thema. Nicht das der Eindruck entsteht, ich finde Geschlechtskrankheiten lustig.
Ich fand nur die Übersetzung witzig...