Ich schreibe eine Template-Klasse, die einen Zeiger als Eingabe nimmt und speichert. Der Zeiger soll auf ein Objekt zeigen, das von einer anderen Klasse zugewiesen wurde, und an die diese enthaltende Klasse übergeben werden.
Nun möchte ich einen Destruktor für diesen Container erstellen. Wie soll ich den Speicher freigeben, auf den dieser Zeiger zeigt? Ich weiß nicht a priori, ob es ein Array oder ein einzelnes Element ist.
Ich bin etwas neu in C ++, also ertragen Sie mit mir. Ich habe immer C verwendet, und Java ist meine OO-Sprache der Wahl, aber zwischen dem Wunsch, C ++ und den Geschwindigkeitsanforderungen meines Projekts zu lernen, bin ich mit C ++ gegangen.
Wäre es eine bessere Idee, den Container von einer Vorlage in einen Container für eine abstrakte Klasse zu ändern, die einen eigenen Destruktor implementieren kann?
Wenn Sie nicht wissen, ob es mit new
oder new[]
zugeordnet wurde, ist es nicht sicher, es zu löschen.
Ihr Code scheint zu funktionieren. Auf einer Plattform, an der ich arbeite, spielt der Unterschied nur eine Rolle, wenn Sie ein Array von Objekten mit Destruktoren haben. Also tust du das:
%Vor%aber dann machst du das:
%Vor%Sie müssen dokumentieren, wie diese Klasse verwendet werden soll, und immer wie erwartet zuweisen. Sie können auch ein Flag an das Objekt übergeben, das angibt, wie es zerstört werden soll. Schauen Sie sich auch die Smartpointer von Boost an, die diese Unterscheidung für Sie übernehmen können.
Kurze Antwort:
Wenn Sie [] mit new verwenden, möchten Sie [] mit delete verwenden.
%Vor%Das waren die nackten Knochen, die andere Sache, die Sie sich ansehen konnten, ist boost . Auch ziemlich schwierig zu beantworten, wenn man bedenkt, dass man nicht sicher ist, ob es ein Array oder ein einzelnes Objekt ist. Sie können dies jedoch über eine Markierung überprüfen, die Ihrer App mitteilt, ob Sie löschen oder löschen möchten [].
Sie sollten es überhaupt nicht löschen. Wenn Ihre Klasse einen bereits initialisierten Zeiger verwendet, ist es nicht sicher, sie zu löschen. Es könnte nicht einmal auf ein Objekt auf dem Heap zeigen; Der Aufruf von delete
oder delete[]
könnte katastrophal sein.
Die Zuweisung und Freigabe von Speicher sollte im selben Umfang erfolgen. Welcher Code auch immer die Instanz Ihrer Klasse besitzt und initialisiert, ist vermutlich auch verantwortlich für die Initialisierung und die Übergabe des Zeigers, und das ist der Ort, an dem Ihr delete
sein sollte.
delete
, wenn Sie mit new
. delete[]
, wenn Sie mit new[]
. Wenn Sie nach diesen Anweisungen weiterhin ein Problem haben (vielleicht möchten Sie ein Objekt löschen, das von jemand anderem erstellt wurde), brechen Sie die dritte Regel:
(Bewegt meinen Kommentar auf Anfrage in eine Antwort.)
JonHs Antwort ist richtig (über die Verwendung der Array-Zerstörung nur bei der Array-Konstruktion), also sollten Sie vielleicht Vorlagen anbieten: eine für Arrays, eine nicht.
Die andere Antwort besteht darin, Arrays zu vermeiden und stattdessen eine einzelne Instanz zu erwarten, die eine richtige Sammlung sein kann oder nicht, die nach sich selbst aufräumt, wie der Vektor & lt; & gt;.
Bearbeiten
Von Roger Pate stehlend, werde ich hinzufügen, dass Sie die Verwendung eines intelligenten Zeigers verlangen könnten, der zu einer Einzelpostensammlung führt.
Wenn Sie eine Klasse haben, die einen Zeiger übernimmt, den sie übernehmen soll, dann muss der Vertrag für die Verwendung der Klasse ein paar Dinge enthalten. Entweder:
oder
delete
für den Zeiger zum Beispiel macht es möglicherweise so einfach wie Option 1 für die meisten Anwendungen). Wenn nun jemand der Klasse einen Zeiger auf ein statisch zugewiesenes Objekt geben will, kann er einen no-op-Funktor übergeben, so dass nichts passiert, wenn die Klasse die Zuordnung aufheben will, oder ein Funktor zu einer delete[]
-Operation, wenn das Objekt zugewiesen wurde von new[]
, etc. Da der Zeiger in C ++ uns nicht sagt, wie er zugewiesen wurde, gibt es keine Möglichkeit, zu entscheiden, welche Methode für die Zuweisung der Freigabe zu verwenden ist. Die Lösung besteht darin, dem Benutzer die Wahl zu geben, der hoffentlich weiß, wie der Speicher zugewiesen wurde. Sehen Sie sich die intelligente Smart-Bibliothek an, besonders bei shared_ptr -Konstruktor mit zweitem Parameter, für ein großartiges Beispiel.
Ein intelligenter Pointer wie Boost shared_pointer hat das bereits abgedeckt, könntest du es benutzen? linky
Einfach ausgedrückt: Wenn man nur einen Zeiger auf dynamisch zugewiesenen Speicher angibt, gibt es keine Möglichkeit, zu bestimmen, wie man ihn sicher zurückweist. Der Zeiger könnte auf eine der folgenden Arten zugewiesen worden sein:
In allen Fällen, bevor Sie den Speicher freigeben können, müssen Sie wissen, wie er zugewiesen wurde.
Tags und Links c++ templates destructor