pointers - golang 中的 slice 不分配任何内存?

标签 pointers go slice

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

它说( slice 部分的第三段):

Because slices are multiword structures, not pointers, the slicing operation does not need to allocate memory, not even for the slice header, which can usually be kept on the stack. This representation makes slices about as cheap to use as passing around explicit pointer and length pairs in C. Go originally represented a slice as a pointer to the structure shown above, but doing so meant that every slice operation allocated a new memory object. Even with a fast allocator, that creates a lot of unnecessary work for the garbage collector, and we found that, as was the case with strings above, programs avoided slicing operations in favor of passing explicit indices. Removing the indirection and the allocation made slices cheap enough to avoid passing explicit indices in most cases.

什么……?为什么它不分配任何内存?如果它是多字结构或指针?它不需要分配内存吗?然后它提到它本来是指向那个slice结构的指针,它需要为一个新的对象分配内存。为什么现在不需要这样做?很困惑

最佳答案

展开Pravin Mishra's answer :

the slicing operation does not need to allocate memory.

“slice 操作”指的是 s1[x:y] 之类的东西,而不是 slice 初始化或 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}

通常像 example 这样的局部变量会被放入栈中。就像这样做而不是使用结构一样:

var exampleData            uintptr
var exampleLen, exampleCap int

那些 example* 变量进入堆栈。 只有当代码确实 return &exampleotherFunc(&example) 或以其他方式允许指向 this 的指针转义时,编译器才会被迫在上分配结构(或 slice 头)堆。

Then it mentions that it was originally a pointer to that slice structure, and it needed to allocate memory for a new object. Why does it not need to do that now?

想象一下,您没有执行上述操作:

example2 := &SliceHeader{…same…}
// or
example3 := new(SliceHeader)
example3.Data = …
example3.Len = …
example3.Cap = …

即类型是 *SliceHeader 而不是 SliceHeader。 根据您提到的内容,这实际上是 slice 过去的样子(Go 1.0 之前)。

它也曾经是 example2example3 都必须在堆上分配。这就是所指的“新对象的内存”。我认为现在逃逸分析将尝试将它们都放入堆栈,只要指针保持在函数的本地,这样它就不再是一个大问题了。不管怎样,避免一级间接寻址是好的,与复制指针并重复取消引用相比,复制三个整数几乎总是更快。

关于pointers - golang 中的 slice 不分配任何内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29196475/

相关文章:

struct - 如何在 slice 内设置结构的字段?

c - 指针表达式:** ptr++,*++ * ptr和++ ** ptr使用

go - 如何检测 ptrace 是否已经在 golang linux 中调用

go - 在 Golang 和 Rust 上使用 Messagepack 编码时的输出不同

python - 如何使用列表切片附加到 python 列表的末尾?

python - 复制列表时 '[:]' 和 '[::]' 切片的区别?

C:查找内存区域中出现的字节

c - C 中的静态数组初始化

c++ - C++ 中指向整数映射和查找的高效指针

linux - GATT 库直接读取特征值,无需遍历服务