这是一个非常简单的问题:
如果可以超过Golang中一个片的容量,那么为什么首先有一个容量参数?
我认为这与内存管理有关,某种“知道如何分配内存中的片”,但我并不确切知道。
发布于 2019-02-20 08:45:20
如果可以超过Golang中一个片的容量,那么为什么首先有一个容量参数?
我不知道你这么说是什么意思,但容量是不能超过的。切片可以被索引到它的长度(排他的),这不能超过容量,并且它们可以被重新分割到它的容量(包括在内)。
表单
a[x]
的主要表达式 如果a
不是地图:...the索引x
在范围内如果是0 <= x < len(a)
,则为超出范围
...the主表达式:
a[low : high]
对于数组或字符串,如果是0 <= low <= high <= len(a)
,则索引在范围内,否则它们超出范围。对于片,上索引界是片容量cap(a)
,而不是长度。
还包括:
...the主表达式:
a[low : high : max]
如果是0 <= low <= high <= max <= cap(a)
,则指数在范围内,否则就超出了范围。
您可以为考虑未来增长的内置make()
提供能力,因此,如果需要向其添加元素或需要重新分配它,则需要更少的分配。内置的append()
只是重新分配您附加到的切片,如果它有足够的容量来处理额外的元素,但是如果它没有容纳新元素的空间,它就必须分配一个新的支持数组(并将现有的内容复制到它中)。append()
将返回新的切片,该切片可能指向或不指向原始支持数组。
让我们看看一个例子。让我们创建一个长度和容量为0的片,并将10个元素附加到其中。为了查看何时发生新的重新分配,我们还打印了它的第一个元素(第0元素)的地址:
fmt.Println("With 0 capacity")
s := make([]int, 0)
for i := 0; i < 10; i++ {
s = append(s, i)
fmt.Println(i, &s[0])
}
这一产出如下:
With 0 capacity
0 0x416030
1 0x416030
2 0x416040
3 0x416040
4 0x452000
5 0x452000
6 0x452000
7 0x452000
8 0x434080
9 0x434080
如您所见,当我们追加第三个(i=2
)、第五个(i=4
)和第九个元素(i=8
)时,以及在追加第一个元素(因为原始支持数组无法容纳任何元素)时,将分配一个新的支持数组。
现在,当我们再次创建长度=0但容量=10的初始切片时,让我们重复上面的示例:
fmt.Println("With 10 capacity")
s = make([]int, 0, 10)
for i := 0; i < 10; i++ {
s = append(s, i)
fmt.Println(i, &s[0])
}
现在的产出将是:
With 10 capacity
0 0x44c030
1 0x44c030
2 0x44c030
3 0x44c030
4 0x44c030
5 0x44c030
6 0x44c030
7 0x44c030
8 0x44c030
9 0x44c030
如您所见,第一个元素的地址从未改变,这意味着后台没有发生新的支持数组分配。
在围棋游乐场上试试这个例子。
发布于 2019-02-20 11:50:53
要增加片的容量,就必须创建一个新的、更大的片,并将原始片的内容复制到其中。
如果在Golang中可以超过一个片的容量,那么为什么首先有一个容量参数?
假设我们提前知道片的容量,那么就可以使用内置函数的容量参数来分配内存,而不是通过追加来动态增加片的容量,这并不是内存效率的问题。
所以在下面的例子中
type Element struct {
Number int
}
func main() {
Max := 100000
startTime := time.Now()
// Capacity given
elements1 := make([]Element, Max, Max)
for i := 0; i < Max; i++ {
elements1[i].Number = i
}
elapsedTime := time.Since(startTime)
fmt.Println("Total Time Taken with Capacity in first place: ", elapsedTime)
startTime = time.Now()
// Capacity not given
elements2 := make([]Element, 0)
for i := 0; i < Max; i++ {
elements2 = append(elements2, Element{Number: i})
}
elapsedTime = time.Since(startTime)
fmt.Println("Total Time Taken without capacity: ", elapsedTime)
}
output
Total Time Taken with Capacity in first place: 121.084µs
Total Time Taken without capacity: 2.720059ms
首先构建具有容量的切片所花费的时间要比动态构建的时间要少。
因此,要回答您的问题,容量参数首先是为了更好的性能和内存效率。
https://stackoverflow.com/questions/54782079
复制相似问题