append()总是扩展所需的最小容量吗?

时间:2013-07-27 19:13:35

标签: go

在学习切片时,我有这样的疑问:append()是否总是扩展所需的最小容量?

a := make([]byte, 0)
a = append(a, 1, 2, 3)
cap(a) == 3  // will this be always true?
// or the assumption may not hold since the underlying implementation of append()
// is not specified.

2 个答案:

答案 0 :(得分:3)

不,在这种情况下无法保证。 specifications说:

append(s S, x ...T) S  // T is the element type of S
  

如果s的容量不足以容纳附加值,则append会分配一个新的足够大的切片,该切片适合现有切片元素和其他值。因此,返回的切片可以引用不同的底层数组。

(强调我的)

在您的情况下,显然任何容量&gt; = 3 足够大,因此可以依赖 cap >= 3,但你不能< / em>依赖cap == 3

当然,你可以假设在这种情况下的上限不会是1e6或1e9或1e12。但是,有意识地没有在每个细节中指定确切的扩大(分配新的后备阵列)策略,以允许编译器人员尝试附加到该机制的一些旋钮。

答案 1 :(得分:2)

我想补充一点,它不仅不保证切片的容量等于长度,事实上,对于大长度,它几乎不会是生成的切片具有容量等于长度的情况。

append()被提升为vector包的替代品。为了做到这一点,附加的复杂性必须与vector包中的复杂性相匹配,这意味着附加元素必须具有分摊的O(1)复杂度。虽然在语言规范中无法保证这种复杂性,但对于现在在Go社区中使用append()的模式来说,它必须是有效的。

为了使append()摊销O(1),它必须在每次空间不足时将容量扩展固定百分比的当前容量。例如,容量翻​​倍。想一想,如果每次耗尽时容量增加一倍,如果长度恰好是2的幂(假设它的最小值为2),则长度和容量只能相同,这不常见。