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

在学习切片时,我有一个疑问: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.


翻翻过去那场雪
浏览 220回答 2
2回答

呼啦一阵风

不,在这种情况下不能保证。该规范说:append(s S, x ...T) S  // T is the element type of S如果 s 的容量不足以容纳附加值,则 append 分配一个新的、足够大的切片,以适合现有切片元素和附加值。因此,返回的切片可能引用不同的底层数组。(强调我的)在你的情况,显然任何容量> = 3是足够大的,所以你可以依靠的cap >= 3,但你不能依靠cap == 3。当然,您可以假设在这种情况下上限不会是,例如 1e6 或 1e9 或 1e12。然而,精确的扩大(分配新的后备数组)策略并没有在每个细节中指定,以允许编译器人员试验一些附加到此机制的旋钮。

摇曳的蔷薇

我要补充的是,它不仅不能保证切片的容量等于长度,事实上,对于大长度,几乎永远不会出现结果切片的容量等于长度的情况。append()被提升为vector包的替代品。为此,追加的复杂度必须与vector包中的复杂度相匹配,这意味着追加元素必须具有分摊 O(1) 的复杂度。尽管在语言规范中没有保证这种复杂性,但对于append()现在在 Go 社区中使用的模式来说,它必须有效地工作。为了append()摊销 O(1),它必须在每次空间用完时以当前容量的固定百分比扩展容量。例如,容量翻倍。想一想,如果每次用完容量翻倍,那么长度和容量只有在长度正好是2的幂(假设它开始是2的幂)的情况下才能相同,这种情况并不常见。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go