为了账号安全,请及时绑定邮箱和手机立即绑定

制作切片大小

制作切片大小

Go
BIG阳 2023-05-15 15:44:25
在 Golang 中,您可以使用以下语法为切片分配内存:my_slice := make( []int, 0 )稍后我可以使用内置的追加函数添加元素,如下所示:my_slice := append(my_slice, 23)我的问题是,如果稍后我们可以继续添加项目,那么在“制作”切片时给出零(或 2 或 5 或其他)有什么区别?尝试猜测切片最终拥有的容量是否有性能奖励?
查看完整描述

2 回答

?
弑天下

TA贡献1818条经验 获得超7个赞

区别在于切片的内存是预先分配的,并len(mySlice)返回切片的总长度。

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

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

  • a如果它有足够的容量,那么它必须重新切片a = a[:len(a)+1]- 这涉及将新切片分配给a附加函数内部。如果 a 没有足够大的容量来“就地”进行追加,则必须分配一个新数组,复制切片中的内容,然后执行分配/追加。

  • 然后分配n给 a [len(a)-1]

  • 然后从 append 函数返回新的切片,并将这个新切片赋值给局部变量a

与之相比,a[i] = n这是一个简单的任务。

查看完整回答
反对 回复 2023-05-15
?
慕森王

TA贡献1777条经验 获得超3个赞

我的问题是,如果稍后我们可以继续添加项目,那么在“制作”切片时给出零(或 2 或 5 或其他)有什么区别?

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

尝试猜测切片最终拥有的容量是否有性能奖励?

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

切片:大小指定长度。切片的容量等于它的长度。可以提供第二个整数参数来指定不同的容量;它必须不小于长度。

例如,make([]int, 0, 10) 分配一个大小为 10 的底层数组,并返回由该底层数组支持的长度为 0、容量为 10 的切片。

从 go doc 复制。

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

make(s, 1)

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

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

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

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

为了避免重新分配发生,我们可以提供可选的容量参数来make告诉我们需要更大的空间。


查看完整回答
反对 回复 2023-05-15
  • 2 回答
  • 0 关注
  • 83 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信