在Golang中,您可以使用以下语法为切片分配内存:
<form action="/test.aspx">
<input type="file" multiple>
<input type="submit">
</form>
<div id="fileList"></div>
然后稍后我可以使用内置的append函数添加元素:
my_slice := make( []int, 0 )
我的问题是,如果“以后”只要我们愿意就继续添加项目,那么在“制作”切片时给零(或2或5或其他)有什么区别?
通过猜测切片最终将具有的容量来获得性能上的好处吗?
答案 0 :(得分:2)
区别在于切片的内存是预先分配的,len(mySlice)
返回切片的总长度。
从性能角度来说,最好预先分配大小,因为调用a = append(a, n)
时会发生以下情况:
它调用内置的append函数,并为此首先复制a
slice(切片标头,后备数组不是标头的一部分),并且必须为可变参数创建临时切片参数,它将包含值n
。
然后,如果它具有a
之类的足够容量,则必须重新切片a = a[:len(a)+1]
-这涉及在append函数中将新切片分配给a
。如果a的容量不足以执行“就地”附加操作,则必须分配一个新数组,复制切片中的内容,然后执行assign / append。
然后将n
分配给[len(a)-1]
。
然后从append函数返回新切片,并将此新切片分配给局部变量a
。
与a[i] = n
相比,这是一个简单的赋值。
答案 1 :(得分:-1)
我的问题是,如果“以后”只要我们愿意就继续添加项目,那么在“制作”切片时给零(或2或5或其他)有什么区别?
分配不当会导致重新分配。
通过猜测切片最终将具有的容量来获得性能上的好处吗?
是的,重新分配将导致切片上的其他副本。
切片:大小指定长度。切片的容量为 等于它的长度。可以提供第二个整数参数 指定不同的容量;它必须不小于长度。
例如,make([] int,0,10)分配一个大小为1的基础数组 10并返回长度为0且容量为10的切片,该切片由 此基础数组。
从go doc复制。
在我看来。切片就像c / c ++中具有长度和容量的指针。追加到切片将在该指针的偏移量之后追加元素。容量是顺序空间的总大小。一旦capacity
-allocated
空间不足,append将在分片上进行重新分配和复制。
make(s, 1)
去做比您想像的要多:
分配一个大于您提供的大小的顺序空间(与c ++向量相同),以避免重新分配,否则可能导致性能降低。
初始化您在make中给出的尺寸。 (RAII)
一旦发生重新分配,go将分配两倍大小的顺序空间,并将旧切片复制到该位置。这也会降低性能。
为避免发生重新分配,我们可以在make
中提供可选的容量参数,以告诉我们我们需要更大的空间。