Sebastians Antwort ist korrekt, aber ich wollte wissen, warum es sicher ist, also habe ich mich ein wenig mit dem Map-Quellcode befasst . Es sieht aus wie bei einem Aufruf von delete(k, v)
, es setzt im Grunde nur ein Flag (sowie das Ändern des Zählwerts), anstatt den Wert tatsächlich zu löschen:
b->tophash[i] = Empty;
(Leer ist eine Konstante für den Wert 0
)
Was die Karte tatsächlich zu tun scheint, ist die Zuweisung einer festgelegten Anzahl von Buckets in Abhängigkeit von der Größe der Karte, die wächst, wenn Sie Einfügungen mit der Rate von 2^B
(aus diesem Quellcode ) ausführen :
byte *buckets; // array of 2^B Buckets. may be nil if count==0.
Es werden also fast immer mehr Buckets zugewiesen, als Sie verwenden. Wenn Sie eine range
Über-die-Karte ausführen, wird der tophash
Wert jedes Buckets darin überprüft, um festzustellen, 2^B
ob er übersprungen werden kann.
Zusammenfassend ist das delete
innerhalb von a range
sicher, da die Daten technisch immer noch vorhanden sind. Wenn es jedoch überprüft tophash
, sieht es, dass es sie einfach überspringen und nicht in die von range
Ihnen ausgeführte Operation einbeziehen kann. Der Quellcode enthält sogar TODO
:
// TODO: consolidate buckets if they are mostly empty
// can only consolidate if there are no live iterators at this size.
Dies erklärt, warum die Verwendung der delete(k,v)
Funktion den Speicher nicht freigibt, sondern nur aus der Liste der Buckets entfernt, auf die Sie zugreifen dürfen. Wenn Sie den eigentlichen Speicher freigeben möchten, müssen Sie die gesamte Karte nicht erreichbar machen, damit die Speicherbereinigung aktiviert wird. Sie können dies mit einer Zeile wie tun
map = nil