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 tophashWert jedes Buckets darin überprüft, um festzustellen, 2^Bob er übersprungen werden kann.
Zusammenfassend ist das deleteinnerhalb von a rangesicher, 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 rangeIhnen 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