Hallo Community,
ich habe vorher nur mit Java zu tun gehabt, deshalb verwirrt mich die
manuelle Speicherfreigabe / Objektlöschung noch ein bisschen.
Ich habe mir eine kleine Test-Klasse geschrieben. Am Ende kann ich
sehen, dass der Destruktor aufgerufen wurde. Die frage die ich mir jetzt
stelle - reicht das? Weil ich immer wieder in Online-Quelltexten sehe,
dass im Destruktor noch mit delete gearbeitet wird. Muss ich die ganzen
angelegten varaiblen innerhalb eines Objektes noch mit delete löschen
lassen, bevor dann die Referenu auf das Objekt durch den Destruktor
gelöscht wird?
Viele Grüße :) !
Lars w. schrieb:> Muss ich die ganzen> angelegten varaiblen innerhalb eines Objektes noch mit delete löschen> lassen,
Wenn die Variablen jeweils mit new angelegt wurden, ja. Zu jedem new
gehört ein korrespondierendes delete.
Wenn du Member mit new erzeugst, musst du sie im Destruktor mit delete
zerstoeren. Fuer solche mit new[] wird delete[] genommen. Fuer malloc
oder calloc wird free() genommen.
Wie immer kann ich hier raten: Schau' dir mal an, was valgrind zu deinem
Programm sagt. Das ist immer sehr interessant -- in Fall von Memory
Leaks hast du was falsch gemacht, wenn am Schluss nicht "definitely
lost: 0" da steht. ;)
Grüße,
Sven
VIelen Dank !
Ich hab mir jetzt Dr.Memory geladen. Dadurch konnte ich schon 2
Speicherleaks in meinem Programm beheben (eben Aufgrund des vergessenen
Deletes bei dynamisch angelegten Speicher per new...).
Ich bin total begeistert ^^
Oft ist auch manuelles Speichermanagement in C++ nicht ideal. Das lohnt
sich nur in manchen Fällen. Es gibt noch weitere Möglichkeiten:
* shared pointer -- macht reference counting. Das hat natürlich einen
gewissen Overhead, ist aber in vielen Fällen egal. Dafür garantiert
diese Methode, dass das Objekt gelöscht wird, genau dann wenn es
nirgends mehr benutzt wird.
* scoped pointer -- wenn man Objekte nur mit "new" anlegt, weil sie zu
groß sind für den Stack, ist das die richtige Methode
* memory pools -- wenn man viele kleine Allokationen braucht, die alle
gemeinsam wieder freigegeben werden sollen, ist das oft auch eine gute
Idee.
Die stdlib hat diverse pointer-Klassen für sowas.
Grüße,
Sven
Und dann ist natürlich noch zu erwähnen, daß man Objekte oft gar nicht
mit new anlegen muß. Wenn man aus der Java-Ecke kommt, ist das ja nicht
selbstverständlich. Es gibt in C++ drei Arten von Speicher, nämlich
statisch, dynamisch und automatisch, und Instanzen jedes Datentyps
können auf jede dieser drei Arten erzeugt werden, egal ob es sich um
Klassen oder eingebaute Typen handelt.
Dabei leben "statische" Objekte bis zum Programm-Ende und werden dann
zerstört, "automatische" Objekte sind lokale Variablen, die beim
Verlassen des Blocks, in dem sie definiert sind, zerstört werden, und
"dynamische" Objekte sind die, die mit new angelegt wurden. Diese (und
nur die) müssen mit delete explizit zerstört werden.
Rolf Magnus schrieb:> Und dann ist natürlich noch zu erwähnen, daß man Objekte oft gar nicht> mit new anlegen muß. Wenn man aus der Java-Ecke kommt
Rolf hat absolut recht.
Gerade die Leute aus der Java oder C# Ecke tendieren dazu, viel zu viel
mittels new anzulegen, weil sie das von Java/C# so gewohnt sind. Dabei
muss man in C++ viel weniger mittels new allokieren und wenn tatsächlich
mal etwas dynamisch allikiert werden muss, dann ist man mit den
Containern der STL oft (aber nicht immer) besser bedient.
Und auch immer an die 'Rule of three' denken: Benötigt man unbedingt
eine der 3 Funktionen Destruktor, Copy Constructor oder
Assignment-Operator, dann benötigt man meistens alle 3.
Macht man selbst dynamisches Memory Management, dann benötigt man auf
jeden Fall alle 3. Selbst wenn 2 davon (CCtor und Op=) lediglich so
trivial verpackt werden, dass sie für Compiler/Linker nicht benutzbar
sind und daher jeder Versuch sie einzusetzen zu einem Compiler/Linker
Fehler führt, der Schlimmeres zur Laufzeit verhindert.
Hallo Karl Heinz,
Karl Heinz Buchegger schrieb:> Dabei> muss man in C++ viel weniger mittels new allokieren und wenn tatsächlich> mal etwas dynamisch allikiert werden muss, dann ist man mit den> Containern der STL oft (aber nicht immer) besser bedient.
Ich tendiere eher umgekehrt: Sie sollten alle nicht-Primitive mit
new/(boost::)shared_ptr anlegen (soweit möglich)...
> Macht man selbst dynamisches Memory Management, dann benötigt man auf> jeden Fall alle 3. Selbst wenn 2 davon (CCtor und Op=) lediglich so> trivial verpackt werden, dass sie für Compiler/Linker nicht benutzbar
...genau, c'ctor und op= lediglich deklarieren um deren (versehentliche)
Nutzung auszuschließen.
Das hat den Vorteil, sie können "normal" weiter programmieren wie bisher
und die (meist) unnötigen (und manchmal auch fehlerhaften) Objektkopien
entfallen. Vor einer op= Zuweisung in C++ wird imho viel weniger
nachgedacht als vor einem copy/clone.
Grüße, Steffen
Steffen schrieb:> Hallo Karl Heinz,>> Karl Heinz Buchegger schrieb:>> Dabei>> muss man in C++ viel weniger mittels new allokieren und wenn tatsächlich>> mal etwas dynamisch allikiert werden muss, dann ist man mit den>> Containern der STL oft (aber nicht immer) besser bedient.>> Ich tendiere eher umgekehrt: Sie sollten alle nicht-Primitive mit> new/(boost::)shared_ptr anlegen (soweit möglich)...
Sofern eine dynamische Allokierung überhaupt notwendig ist - das ist der
springende Punkt auf den ich raus will.
Hallo nochmal,
vielen Dank für die weiteren Hinweise, ich denke, ich habe es jetz
verstanden. Ich versuche auch möglichst nicht mi new* o.ä zu arbeiten.
Allerdings benötige ich für ein kleines Spiel ein dynamisches Array,
daher bin ich darauf gekommen.
Lars w. schrieb:> Hallo nochmal,>> vielen Dank für die weiteren Hinweise, ich denke, ich habe es jetz> verstanden. Ich versuche auch möglichst nicht mi new* o.ä zu arbeiten.> Allerdings benötige ich für ein kleines Spiel ein dynamisches Array,> daher bin ich darauf gekommen.
std::vector ist dein Freund.