1

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

2 回答 2

3

不,在这种情况下不能保证。规格说:

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

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

(强调我的)

在您的情况下,显然任何容量 >= 3 都足够大,因此您可以依赖cap >= 3不能依赖cap == 3

当然,您可以假设在这种情况下上限不会是 1e6 或 1e9 或 1e12。然而,我们故意没有在每个细节中指定精确的扩大(分配新的支持数组)策略,以允许编译器人员尝试使用附加到此机制的一些旋钮。

于 2013-07-27T19:41:08.027 回答
2

我要补充一点,它不仅不能保证切片的容量等于长度,事实上,对于大长度,几乎永远不会出现结果切片的容量等于长度的情况。

append()被提升为vector包的替代品。为了做到这一点,追加的复杂度必须与vector包中的复杂度相匹配,这意味着追加元素必须具有摊销的 O(1) 复杂度。append()尽管在语言规范中并不能保证这种复杂性,但Go 社区现在使用的模式必须如此才能有效地工作。

为了append()摊销 O(1),每次空间用完时,它必须将容量扩展为当前容量的固定百分比。例如,容量翻​​倍。想想看,如果每次用完容量都翻倍,那么只有长度正好是 2 的幂(假设一开始是 2 的幂),长度和容量才能相同,这并不常见。

于 2013-07-27T22:49:20.497 回答