La risposta di Sebastian è accurata, ma volevo sapere perché era sicura, quindi ho fatto qualche ricerca nel codice sorgente della mappa . Sembra su una chiamata a delete(k, v)
, in pratica imposta solo un flag (oltre a cambiare il valore del conteggio) invece di eliminare effettivamente il valore:
b->tophash[i] = Empty;
(Vuoto è una costante per il valore 0
)
Ciò che la mappa sembra effettivamente fare è l'allocazione di un determinato numero di bucket in base alla dimensione della mappa, che aumenta man mano che si eseguono inserti al ritmo di 2^B
(da questo codice sorgente ):
byte *buckets; // array of 2^B Buckets. may be nil if count==0.
Quindi ci sono quasi sempre più bucket allocati di quelli che stai usando e quando fai un range
over sulla mappa, controlla quel tophash
valore di ogni bucket in quello 2^B
per vedere se può saltarci sopra.
Riassumendo, l' delete
interno arange
è sicuro perché i dati sono tecnicamente ancora lì, ma quando li controlla tophash
vede che può semplicemente ignorarli e non includerli in qualsiasi range
operazione tu stia eseguendo. Il codice sorgente include anche un TODO
:
// TODO: consolidate buckets if they are mostly empty
// can only consolidate if there are no live iterators at this size.
Questo spiega perché l'uso della delete(k,v)
funzione in realtà non libera memoria, la rimuove semplicemente dall'elenco dei bucket a cui è consentito accedere. Se vuoi liberare la memoria effettiva dovrai rendere irraggiungibile l'intera mappa in modo che la raccolta dei rifiuti possa intervenire. Puoi farlo usando una linea come
map = nil