制作切片大小

Make slices size

在 Golang 中,您可以使用以下语法为切片分配内存:

my_slice := make( []int, 0 )

稍后我可以使用内置追加函数添加元素:

my_slice := append(my_slice, 23)

我的问题是,当 "making" 切片时给零(或 2 或 5 或其他)有什么区别,如果稍后我们可以继续添加项目,只要我们想?

是否可以通过尝试猜测切片最终拥有的容量来获得性能奖励?

不同之处在于切片的内存是预先分配的,len(mySlice) returns 切片总长度。

在性能方面,预先分配大小是有益的,因为当您调用 a = append(a, n) 时会发生以下情况:

  • 它调用内置的附加函数,为此它首先复制 a 切片(切片头,支持数组不是头的一部分),它必须创建一个临时的包含值 n.

  • 的可变参数的切片
  • 然后它必须重新切片 a 如果它有足够的容量像 a = a[:len(a)+1] - 这涉及将新切片分配给附加函数内的 a 。如果 a 没有足够大的容量来执行追加 "in-place" 则必须分配一个新数组,复制切片中的内容,然后执行分配/追加。

  • 然后将n赋值给一个[len(a)-1].

  • 然后returns从append函数中得到新的slice,并将这个新的slice赋值给局部变量a.

a[i] = n 相比,这是一个简单的赋值。

My question is, what's the difference between giving that zero ( or 2 or 5 or whatever) when "making" the slice if later on we can keep adding items as long as we wan?

分配不当会导致重新分配。

Is there a performance bonus by trying to guess the capacity that slice will end up having?

是的,重新分配会导致切片上有额外的副本。

Slice: The size specifies the length. The capacity of the slice is equal to its length. A second integer argument may be provided to specify a different capacity; it must be no smaller than the length.

For example, make([]int, 0, 10) allocates an underlying array of size 10 and returns a slice of length 0 and capacity 10 that is backed by this underlying array.

从 go doc 复制。

在我看来。在c/c++中,Slice 就像一个具有长度和容量 的指针。附加到切片将在该指针的偏移量之后附加元素。容量是总顺序 space 大小。一旦capacity-allocatedspace不够用,append会导致重新分配,并在slice上复制。

make(s, 1)

go 会做的比你想象的要多:

  1. 分配一个比您给定的大小更大的顺序 space(在 C++ 向量中相同)以避免可能导致性能低下的重新分配。

  2. 初始化你在make中给定的尺寸。 (RAII)

  3. 一旦重新分配发生,go 将分配两倍大小的顺序 space 并将旧切片复制到该位置。这也会降低性能。

为了避免重新分配发生,我们可以在 make 中提供可选的容量参数来告诉 go 我们需要更大的 space.