golang中的切片不分配任何内存?

此链接:http : //research.swtch.com/godata

它说(切片部分的第三段):

因为切片是多字结构,而不是指针,切片操作不需要分配内存,甚至不需要分配内存,切片头通常可以保存在堆栈中。这种表示使得切片的使用与在 C 中传递显式指针和长度对一样便宜。Go 最初将切片表示为指向上述结构的指针,但这样做意味着每个切片操作都分配了一个新的内存对象。即使使用快速分配器,这也会为垃圾收集器带来大量不必要的工作,而且我们发现,就像上面的字符串一样,程序避免了切片操作,而转而传递显式索引。删除间接和分配使切片足够便宜,以避免在大多数情况下传递显式索引。

什么...?为什么它不分配任何内存?如果是多字结构还是指针?不需要分配内存吗?然后它提到它最初是指向该切片结构的指针,并且需要为新对象分配内存。为什么现在不需要这样做?非常困惑


墨色风雨
浏览 263回答 2
2回答

慕标琳琳

扩展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]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // <<- does not (normally) allocate也就是说,第二行类似于:type SliceHeader struct {&nbsp; &nbsp; &nbsp; &nbsp; Data uintptr&nbsp; &nbsp; &nbsp; &nbsp; Len&nbsp; int&nbsp; &nbsp; &nbsp; &nbsp; Cap&nbsp; int}…example := SliceHeader{&s1[1], 2, 5}通常像exampleget这样的局部变量被放入堆栈。就像这样做而不是使用结构一样:var exampleData&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; uintptrvar exampleLen, exampleCap int这些example*变量进入堆栈。只有当代码确实return &example或otherFunc(&example)以其他方式允许指向 this 的指针转义时,编译器才会被迫在堆上分配结构(或切片头)。然后它提到它最初是指向该切片结构的指针,并且需要为新对象分配内存。为什么现在不需要这样做?想象一下,你所做的不是上面的:example2 := &SliceHeader{…same…}// orexample3 := new(SliceHeader)example3.Data = …example3.Len = …example3.Cap = …即类型是*SliceHeader而不是SliceHeader。根据您提到的内容,这实际上是切片过去的样子(Go 1.0 之前)。它也曾经是这两个example2,并example3会对堆进行分配。这就是所指的“新对象的内存”。我认为现在转义分析将尝试将这两个都放入堆栈,只要指针保持在函数的本地,所以它不再是一个大问题。无论哪种方式,避免一级间接都是好的,与复制指针并重复取消引用相比,复制三个整数几乎总是更快。

ibeautiful

每种数据类型在初始化时都会分配内存。在博客中,他明确提到切片操作不需要分配内存。他是对的。现在看看slice 在 golang 中是如何工作的。切片保存对底层数组的引用,如果将一个切片分配给另一个切片,则两者都引用同一个数组。如果一个函数接受一个切片参数,它对切片元素所做的更改将对调用者可见,类似于传递一个指向底层数组的指针。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go