2 回答
TA贡献1830条经验 获得超9个赞
扩展Pravin Mishra 的回答:
切片操作不需要分配内存。
“切片操作”指的是诸如s1[x:y]而不是切片初始化或make([]int, x). 例如:
var s1 = []int{0, 1, 2, 3, 4, 5} // <<- allocates (or put on stack)
s2 := s1[1:3] // <<- does not (normally) allocate
也就是说,第二行类似于:
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
…
example := SliceHeader{&s1[1], 2, 5}
通常像exampleget这样的局部变量被放入堆栈。就像这样做而不是使用结构一样:
var exampleData uintptr
var exampleLen, exampleCap int
这些example*变量进入堆栈。只有当代码确实return &example或otherFunc(&example)以其他方式允许指向 this 的指针转义时,编译器才会被迫在堆上分配结构(或切片头)。
然后它提到它最初是指向该切片结构的指针,并且需要为新对象分配内存。为什么现在不需要这样做?
想象一下,你所做的不是上面的:
example2 := &SliceHeader{…same…}
// or
example3 := new(SliceHeader)
example3.Data = …
example3.Len = …
example3.Cap = …
即类型是*SliceHeader而不是SliceHeader。根据您提到的内容,这实际上是切片过去的样子(Go 1.0 之前)。
它也曾经是这两个example2,并example3会对堆进行分配。这就是所指的“新对象的内存”。我认为现在转义分析将尝试将这两个都放入堆栈,只要指针保持在函数的本地,所以它不再是一个大问题。无论哪种方式,避免一级间接都是好的,与复制指针并重复取消引用相比,复制三个整数几乎总是更快。
TA贡献1993条经验 获得超5个赞
每种数据类型在初始化时都会分配内存。在博客中,他明确提到
切片操作不需要分配内存。
他是对的。现在看看slice 在 golang 中是如何工作的。
切片保存对底层数组的引用,如果将一个切片分配给另一个切片,则两者都引用同一个数组。如果一个函数接受一个切片参数,它对切片元素所做的更改将对调用者可见,类似于传递一个指向底层数组的指针。
- 2 回答
- 0 关注
- 262 浏览
添加回答
举报