Löschen der Klasse aus einer Funktion
-
volkard schrieb:
Das ist keine gute Idee. Praxisfern.
okay...
Dann mal nen Praxisbeispiel, wo ich sowas z.B. verwenden würde:
Ein ganz einfacher binärer Baum (mit vielen binären Knoten)
Wenn ich jetzt ein Element in einen Knoten einfügen wollte, würde ich
z.B.right = new Node(inhalt);machen
Später möchte ich diesen Eintrag wieder entfernen.
Dann mach ich:delete right; right = 0;so garantiere ich, dass mein Destruktor mit
delete right; delete left;funktioniert.
Würdest du in so einem Fall anders vorgehen oder siehst du es als 'Ausnahme'
Fällt mir gerade auf... Ich hätte auch ne lineare Liste nehmen können

volkard schrieb:
Zu jedem new gehört ein delete.
Aber generell gebe ich dir da absolut recht!

-
Du hast anscheinend übersehen das in dem Code-Beispiel das er kritisiert hat eine lokale Kopie eines Pointers auf 0 gesetzt wird...
-
Natürlich gibt es Fälle, wo man Zeiger nach dem Freigeben auf Null setzt. Doch wenn man kein Containerbastler ist, tritt das meines Erachtens eher weniger auf. Ich weiss nicht, wann ich sowas das letzte Mal benötigt habe. Selbst ein selbstgeschriebenes
deleteausserhalb einer Smart-Pointer-Implementierung ist schon länger her.Ich meine nur, dass ein
scoped_ptr<T> ptr(new T(1)); ptr.reset(new T(2));tausendmal sicherer ist als jedes noch so "safe"
delete. Und in der Regel sollte man im Anwendungscode zu Smart-Pointern tendieren, wenn überhaupt Zeiger benötigt werden (was oft nicht nötig ist).
-
Hab noch nie Smart-Pointer etc. verwendet. Gab noch nie Probleme. Wobei der Code auf über 15 Jahre alt ist...
-
Fellhuhn schrieb:
Du hast anscheinend übersehen das in dem Code-Beispiel das er kritisiert hat eine lokale Kopie eines Pointers auf 0 gesetzt wird...
Ich denke er meinte das wxWidgets-Beispiel, oder?
Das mit der lokalen Kopie hab ich gesehen:
CSpille schrieb:
Außerdem kannst mir den Zweck von
f= NULL;noch erklären

-
Fellhuhn schrieb:
Hab noch nie Smart-Pointer etc. verwendet. Gab noch nie Probleme. Wobei der Code auf über 15 Jahre alt ist...
Du meinst, du hast noch keine Probleme entdeckt.

Natürlich geht es auch ohne Smart-Pointer, sieht man ja an C. Aber es wird bei komplexeren Situationen relativ lästig, besonders wenn Exceptions oder mehrere Ablaufpfade hinzukommen.
Wie löst du das? Das ist jetzt nicht einmal ein gekünsteltes Beispiel, sondern kommt ziemlich ähnlich bei mir vor. Und das Beispiel ist noch eher einfach, da alles nach dem selben Muster abläuft. Die Membervariablen sind momentan vom Typ
scoped_ptrmit dem entsprechenden Zeigertypen. Die Ressourcen werfen im Konstruktor eine Exception, falls sie nicht geladen werden können.void MyClass::LoadResources() { myGraphics.reset( new GraphicResource() ); // Lädt alle Grafiken myAudio.reset( new AudioResource() ); // Lädt alle Sounds myFonts.reset( new FontResource() ); // Lädt alle Schriftarten myData.reset( new DataResource() ); // Lädt sonstige Daten }Du hast fast immer mehr und komplexeren Code, wenn du solche Probleme äquivalent ohne RAII lösen möchtest.
-
Nexus schrieb:
Ich meine nur, dass ein
scoped_ptr<T> ptr(new T(1)); ptr.reset(new T(2));tausendmal sicherer ist als jedes noch so "safe"
delete. Und in der Regel sollte man im Anwendungscode zu Smart-Pointern tendieren, wenn überhaupt Zeiger benötigt werden (was oft nicht nötig ist).Machst du in deine Klassen eigentlich scoped_ptr<T> statt normale Pointer?
Also wo ich mir nie so die Gedanken drüber gemacht habe, was mir gerade auffällt:
Mir war ja klar, dass man im Konstruktor alles selbst aufräumen muss, falls eine
Exception fliegt. (passiert ja relativ selten ^^ - Ich weiß: falsche Einstellung)
Wenn man jetzt zwei Objekte auf dem Heap anlegt und beim zweiten eine bad_alloc
fliegt, dann hat man ja ein memory leak...
Wenn man stattdessen einen scoped_ptr verwendet jedoch nicht...DANKE Nexus!
Ohne deine (erneute)
Smart-Pointer Befürwortung wäre mir das wohl jetzt
nicht aufgefallen.
-
CSpille schrieb:
Würdest du in so einem Fall anders vorgehen oder siehst du es als 'Ausnahme'
Ich sehe das als einen ganz anderen Fall. Hier ist die Liste so definiert, daß der letzte Zeiger 0 enthält und man daran das Ende erkennt.
Mir fiel auf, daß Du im Baum Code zwei Zeilen
CSpille schrieb:
delete right; right = 0;geschrieben hast.
frei nach CSpille schrieb:
void removeLast() {//ungetestet Node** last=&first; while((*last)->next!=0) last=&(last->next); delete last; last=0; }recht lustig schrieb:
void removeLast() {//ungetestet Node** last=&first; while((*last)->next!=0) last=&(last->next); safeDelete(last);//oder wxDELETE(last); }
-
CSpille schrieb:
Machst du in deine Klassen eigentlich scoped_ptr<T> statt normale Pointer?
Nicht
scoped_ptrstatt normalen Zeigern, sondernscoped_ptrstatt besitz-an-sich-reissenden, nicht-teilenden Zeigern.
Wenn der Zeiger lediglich ein Verweis auf andere Daten ist, nehme ich natürlich keinen Smart-Pointer. Es gibt z.B. auch ab und zu den Fall, in dem ich einen Zeiger tief kopieren möchte. Da leider Boost und auch die Standardbibliothek nichts dergleichen bieten und Lokis Implementierung auch nur begrenzt weiterhilft, habe ich mir selbst entsprechende Smart-Pointer geschrieben, die in ihrem Kopierkonstruktor das Objekt kopieren, die virtuelle
Clone()-Funktion aufrufen oder sonst was tun...
-
volkard schrieb:
Ich sehe das als einen ganz anderen Fall. Hier ist die Liste so definiert, daß der letzte Zeiger 0 enthält und man daran das Ende erkennt.
Sehr gut...
Deine Kritik ging also gegen 'unüberlegtes' präventives setzen auf 0,
quasi als 'Allerheilmittel' für fehlende Zuordnung der Löschverantwortungthx!