Ich verwende std::map
, um String-Werte zu MyType *
zuzuordnen. Meine Kartendeklaration sieht folgendermaßen aus:
my_map
ist eine private Member-Variable einer meiner Klassen. Mein Problem ist, dass ich mir nicht sicher bin, wie ich die Karte zerstören soll. Wenn ich die Karte lösche, möchte ich auch delete
für alle in der Karte enthaltenen MyType *
aufrufen. Hier ist mein aktueller Destruktor:
Löscht das die Zeiger, die in der Karte enthalten sind, oder muss ich durch die Karte iterieren, um jeden Zeiger vor dem Löschen zu löschen?
Zeiger zeigen nur. Wenn Sie rohe Zeiger verwenden, müssen Sie wissen, welcher Teil Ihrer App die Ressourcen besitzt, auf die die Zeiger zeigen. Wenn sie der Karte gehören, müssen Sie über die Karte iterieren und für jeden Zeiger delete aufrufen, bevor die Karte zerstört wird. Wenn die Map jedoch nur Zeiger auf Objekte enthält, die anderen Teilen Ihres Codes gehören, müssen Sie nichts tun.
Eine sicherere Lösung besteht darin, shared_ptr zum Verwalten der Objektlebensdauer zu verwenden, wodurch sichergestellt wird, dass das Objekt ordnungsgemäß gelöscht wird, wenn das letzte shared_ptr zerstört wird. Sie können shared_ptrs in der Map speichern. Wenn keine anderen shared_ptr-Instanzen auf die Objekte innerhalb der Map verweisen, werden die Objekte bei Bedarf zerstört, wenn die Map zerstört wird.
Löscht das die Zeiger in der Karte [...]?
Nein, mit dem von Ihnen angegebenen Code werden Sie jedes Mitglied der Karte verlassen.
In der Regel muss für jedes new
ein passendes delete
vorhanden sein. Sie haben eine delete
für die Karte, aber keine für die Elemente innerhalb.
Die beste Lösung für dieses Problem besteht darin, keine dynamische Zuweisung zu verwenden. Speichern Sie das Verzeichnis MyType
s, falls möglich:
map<string, MyType>
... und anstatt das map
selbst dynamisch zuzuweisen, speichern Sie das automatisch:
Wenn die automatische Speicherdauer aus irgendeinem Grund nicht möglich ist, verwenden Sie einen intelligenten Zeiger für die dynamischen Zuordnungen. Bei einem C ++ 11-Compiler verwenden Sie unique_ptr
(oder selten shared_ptr
oder sogar weak_ptr
) für die Elemente in map
:
(Bei einem C ++ 03-Compiler verwenden Sie die Boost-Äquivalente.) Wenn my_map
dann zerstört wird, sind alle Elemente delete
d.
Wenn Sie all dies ignorieren, wenn Sie sich in einer Situation befinden, in der nichts von dem oben genannten für Sie funktioniert (ich würde es sehr verdächtigen), dann müssen Sie die Karte selbst iterieren:
%Vor%In C ++ 11 könnte dies ein Lambda sein, etwas entlang der folgenden Zeile:
%Vor%Wenn Sie intelligente Zeiger anstelle von rohen Zeigern verwenden, wird alles automatisch für Sie bereinigt.
%Vor%Machen Sie Ihr Leben im modernen C ++ einfacher und verwenden Sie nur Zeiger nur , wenn dies unbedingt erforderlich ist.
Sie haben mit diesem Code angefangen:
%Vor%
Als Erstes können Sie eine std::map
-Instanz als Datenelement anstelle eines -Zeichens verwenden.
Dann, wenn MyType
nicht sehr teuer zu kopieren ist und seine Instanzen nur Eigentum der Karte sind, betrachten Sie einfach eine einfache map
von string
bis MyType
(anstelle von MyType*
):
Wenn Sie wirklich eine Karte benötigen, die Zeiger enthält, sollten Sie intelligente Zeiger , wie std::shared_ptr
(verfügbar in C ++ 11/14), für die gemeinsame Eigentümerschaft oder std::unique_ptr
für eindeutige Nicht-Eigentümer verwenden. gemeinsames Eigentum.
(Wenn Sie C ++ 98/03 als Ziel haben, verwenden Sie boost::shared_ptr
. Da es keine Semantik für Umzüge gibt, können Sie nicht unique_ptr
haben, was stark auf der Funktion zum Verschieben von Semantiken basiert.)
z.B.:
Wie Sie sehen können, können Sie mit Wert Semantik (anstelle von rohen Zeigern) oder Smart Zeigern Ihren Code vereinfachen und die automatische Zerstörung