提问人:Daniel Richter 提问时间:12/12/2022 最后编辑:Jonathan HallDaniel Richter 更新时间:12/13/2022 访问量:336
当 Go 将切片移动到内存中的另一个位置时,指向元素的指针会发生什么情况?
What happens to pointer to element when Go moves slice to another place in memory?
问:
我有以下代码
package main
import "fmt"
func main() {
a := []int{1}
b := &a[0]
fmt.Println(a, &a[0], b, *b) // prints [1] 0xc00001c030 0xc00001c030 1
a = append(a, 1, 2, 3)
fmt.Println(a, &a[0], b, *b) // prints [1 1 2 3] 0xc000100020 0xc00001c030 1
}
首先,它创建一个 1 int 的切片。它的 len 是 1,cap 也是 1。然后,我将指针指向它的第一个元素,并获取打印中的基础指针值。正如预期的那样,它工作正常。
比我向切片添加 3 个元素,使 go 扩展切片的容量,从而将其复制到内存中的另一个位置。之后,我打印切片第一个元素的地址(通过指针),该元素现在与存储在 中的地址不同。b
但是,当我打印它的基础值时,它也可以正常工作。我不明白它为什么有效。据我所知,第一个元素指向的切片被复制到内存中的另一个位置,因此它以前的内存一定已被释放。然而,它似乎仍然存在。b
b
如果我们在地图上查看,golang 甚至不允许我们逐键创建元素指针,因为存在完全相同的问题 - 基础数据可以移动到内存中的另一个位置。但是,它与切片配合得很好。为什么会这样?它到底是如何工作的?内存是否未被释放,因为仍然有一个变量指向此内存?它与地图有何不同?
答:
当 Go 将切片移动到内存中的另一个位置时,指向元素的指针会发生什么情况?
无。
[W]然后我打印它的基础值也很好用。我不明白它为什么有效。
b
为什么它不起作用?
最初指向的内存位置仍然存在,没有改变。只要任何内容(例如)仍然引用它,它就会保持可用。一旦删除了对该内存的所有引用(即超出范围),垃圾回收器可能会允许它被其他东西使用。b
当 Go 将切片移动到另一个元素时,指向元素的指针会发生什么情况 在记忆中的位置?
我相信当前的 GC 实现根本不会移动此类对象,尽管规范允许这种情况发生。除非你使用“不安全”的包,否则你不太可能遇到任何问题,即使它确实移动了底层数据结构。
上一个:切片到指针映射重复值
评论
append