Ответ Себастьяна точен, но я хотел знать, почему это безопасно, поэтому я немного покопался в исходном коде карты . Похоже, что при вызове delete(k, v)
он просто устанавливает флаг (а также меняет значение счетчика) вместо фактического удаления значения:
b->tophash[i] = Empty;
(Пусто - это константа для значения 0
)
На самом деле карта, по-видимому, выделяет определенное количество сегментов в зависимости от размера карты, который увеличивается по мере выполнения вставок со скоростью 2^B
(из этого исходного кода ):
byte *buckets; // array of 2^B Buckets. may be nil if count==0.
Таким образом, почти всегда выделяется больше сегментов, чем вы используете, и когда вы выполняете range
переход по карте, он проверяет это tophash
значение каждого сегмента в нем, 2^B
чтобы увидеть, может ли он пропустить его.
Подводя итог, можно сказать, что delete
внутри a range
безопасно, потому что данные технически все еще там, но когда он проверяет, tophash
он видит, что может просто пропустить их и не включать в любую range
операцию, которую вы выполняете. Исходный код даже включает TODO
:
// TODO: consolidate buckets if they are mostly empty
// can only consolidate if there are no live iterators at this size.
Это объясняет, почему использование delete(k,v)
функции на самом деле не освобождает память, а просто удаляет ее из списка сегментов, к которым вам разрешен доступ. Если вы хотите освободить реальную память, вам нужно сделать всю карту недоступной, чтобы вмешалась сборка мусора. Вы можете сделать это, используя строку вида
map = nil