亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

為什么 Go 禁止取 (&) 映射成員的地址,而允許 (&) 切片元素?

為什么 Go 禁止取 (&) 映射成員的地址,而允許 (&) 切片元素?

Go
冉冉說 2021-11-08 14:36:33
Go 不允許獲取地圖成員的地址:// if I do this:p := &mm["abc"]// Syntax Error - cannot take the address of mm["abc"]基本原理是,如果 Go 允許獲取此地址,則當 map backstore 增長或縮小時,該地址可能會變得無效,從而使用戶感到困惑。但是當 Go 切片超出其容量時會重新定位,然而,Go 允許我們獲取切片元素的地址: a := make([]Test, 5) a[0] = Test{1, "dsfds"} a[1] = Test{2, "sdfd"} a[2] = Test{3, "dsf"} addr1 := reflect.ValueOf(&a[2]).Pointer() fmt.Println("Address of a[2]: ", addr1) a = append(a, Test{4, "ssdf"}) addrx := reflect.ValueOf(&a[2]).Pointer() fmt.Println("Address of a[2] After Append:", addrx) // Note after append, the first address is invalid Address of a[2]:  833358258224 Address of a[2] After Append: 833358266416為什么 Go 是這樣設計的?取切片元素的地址有什么特別之處?
查看完整描述

2 回答

?
慕萊塢森

TA貢獻1810條經驗 獲得超4個贊

切片和映射之間有一個主要區別:切片由支持數組支持,而映射則沒有。

如果地圖增長或縮小,則指向地圖元素的潛在指針可能會變成指向無處的懸空指針(未初始化的內存)。這里的問題不是“用戶的困惑”,而是它會破壞 Go 的一個主要設計元素:沒有懸空指針。

如果切片容量不足,則會創建一個新的、更大的后備陣列,并將舊的后備陣列復制到新的后備陣列中;并且舊的支持數組仍然 存在。因此,從指向舊支持數組的“未生成”切片獲得的任何指針仍然是指向有效內存的有效指針。

如果您的切片仍然指向舊的支持數組(例如,因為您在切片超出其容量之前制作了切片的副本),您仍然可以訪問舊的支持數組。這與切片元素的指針關系不大,但切片是數組的視圖,并且在切片增長期間復制數組。

請注意,在切片收縮期間沒有“減少切片的支持數組”。


查看完整回答
反對 回復 2021-11-08
?
POPMUISE

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] 以避免程序的微妙錯誤,這些錯誤可能會長時間保留指針而沒有意識到它會指向與程序員所想的不同的數據。


查看完整回答
反對 回復 2021-11-08
  • 2 回答
  • 0 關注
  • 273 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號