Câu trả lời của Sebastian là chính xác, nhưng tôi muốn biết tại sao nó an toàn, vì vậy tôi đã đào sâu vào mã nguồn Map . Có vẻ như trong một cuộc gọi đến delete(k, v)
, về cơ bản nó chỉ đặt một cờ (cũng như thay đổi giá trị đếm) thay vì thực sự xóa giá trị:
b->tophash[i] = Empty;
(Trống là hằng số cho giá trị 0
)
Những gì bản đồ dường như thực sự đang làm là phân bổ một số nhóm đã đặt tùy thuộc vào kích thước của bản đồ, sẽ tăng lên khi bạn thực hiện chèn theo tỷ lệ 2^B
(từ mã nguồn này ):
byte *buckets; // array of 2^B Buckets. may be nil if count==0.
Vì vậy, hầu như luôn có nhiều thùng được phân bổ hơn so với bạn đang sử dụng và khi bạn thực hiện range
trên bản đồ, nó sẽ kiểm tra tophash
giá trị của từng nhóm trong đó 2^B
để xem liệu nó có thể bỏ qua không.
Tóm lại, delete
bên trong a range
là an toàn vì dữ liệu vẫn còn ở đó, nhưng khi kiểm tra tophash
nó thấy rằng nó chỉ có thể bỏ qua nó và không bao gồm nó trong bất kỳ range
hoạt động nào bạn đang thực hiện. Mã nguồn thậm chí bao gồm TODO
:
// TODO: consolidate buckets if they are mostly empty
// can only consolidate if there are no live iterators at this size.
Điều này giải thích tại sao việc sử dụng delete(k,v)
chức năng không thực sự giải phóng bộ nhớ, chỉ cần xóa nó khỏi danh sách các nhóm bạn được phép truy cập. Nếu bạn muốn giải phóng bộ nhớ thực, bạn sẽ cần làm cho toàn bộ bản đồ không thể truy cập được để bộ sưu tập rác sẽ bước vào. Bạn có thể thực hiện việc này bằng cách sử dụng một dòng như
map = nil