2 回答

TA貢獻1810條經驗 獲得超4個贊
切片和映射之間有一個主要區別:切片由支持數組支持,而映射則沒有。
如果地圖增長或縮小,則指向地圖元素的潛在指針可能會變成指向無處的懸空指針(未初始化的內存)。這里的問題不是“用戶的困惑”,而是它會破壞 Go 的一個主要設計元素:沒有懸空指針。
如果切片容量不足,則會創建一個新的、更大的后備陣列,并將舊的后備陣列復制到新的后備陣列中;并且舊的支持數組仍然 存在。因此,從指向舊支持數組的“未生成”切片獲得的任何指針仍然是指向有效內存的有效指針。
如果您的切片仍然指向舊的支持數組(例如,因為您在切片超出其容量之前制作了切片的副本),您仍然可以訪問舊的支持數組。這與切片元素的指針關系不大,但切片是數組的視圖,并且在切片增長期間復制數組。
請注意,在切片收縮期間沒有“減少切片的支持數組”。

TA貢獻1765條經驗 獲得超5個贊
map 和 slice 之間的根本區別在于,map 是一種動態數據結構,可隨著其增長移動其包含的值。Go map 的具體實現甚至可能會增量增長,在插入和刪除操作期間一點點增長,直到所有值都移動到更大的內存結構。所以你可能會刪除一個值,突然另一個值可能會移動。另一方面,切片只是指向子數組的接口/指針。切片永遠不會增長。append 函數可以將一個切片復制到另一個容量更大的切片中,但它會保持舊切片完好無損,而且它也是一個函數,而不僅僅是一個索引運算符。
用地圖實現者自己的話來說:
https://www.youtube.com/watch?v=Tl7mi9QmLns&feature=youtu.be&t=21m45s “它干擾了這個不斷增長的過程,所以如果我獲取存儲桶中某個條目的地址,然后我將該條目保留在很長一段時間,同時映射增長,然后突然間該指針指向舊存儲桶而不是新存儲桶,并且該指針現在無效,因此很難提供獲取值地址的能力一張地圖,不限制增長的工作方式...... C++ 以不同的方式增長,因此您可以獲取桶的地址”
因此,即使 &m[x] 可以被允許并且對短期操作很有用(對值進行修改,然后不再使用該指針),實際上映射內部是這樣做的,我認為語言設計者/實現者選擇使用 map 保持安全,不允許 &m[x] 以避免程序的微妙錯誤,這些錯誤可能會長時間保留指針而沒有意識到它會指向與程序員所想的不同的數據。
- 2 回答
- 0 關注
- 273 瀏覽
添加回答
舉報