Відповідь Себастьяна точна, але я хотів дізнатися, чому це безпечно, тому я трохи перекопався у вихідному коді карти . Це виглядає як під час виклику до 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