Swift array.capacity vs array.count

时间:2015-01-07 23:22:04

标签: arrays swift

我理解array.count(数组中元素的数量)。 count对迭代数组元素非常有用。我有点得到array.capacity的要点

  

capacity一个整数值,表示总元素的数量   数组可以存储而无需重新分配(只读)。

实验

我一直在玩Playground并注意到数组的容量是偶数(递增2)

var arr = [1, 2, 3 , 4, 5, 6, 7]
arr.removeLast() // capacity stays the same after a removal
println(arr.capacity) // 8
println(arr.count)    // 6

var arr = [1, 2, 3 , 4, 5, 6]
arr.removeLast()
println(arr.capacity) // 6
println(arr.count)    // 5

问题

阵列容量有什么用?请举一个具体的例子?

3 个答案:

答案 0 :(得分:15)

数组的容量 - 特别是它的reserveCapacity方法 - 允许您预先分配数组中的空间。

如果您要向阵列添加元素,并且超出其容量,则阵列必须增加其容量。由于Swift数组将其元素连续存储在内存中,因此必须重新分配其内部存储并(通常)将其所有元素从旧存储复制到新存储。 (请注意,NSArray没有记录以连续存储其元素,但我们可以推断出Swift数组可能基于withUnsafeMutableBufferPointer方法的存在。)

如果您事先知道 要添加到阵列中的元素数量,您可以使用reserveCapacity方法预设数组的容量,以便赢得&# 39; t需要执行任何重新分配(以及相关的复制)。

我可以考虑向阵列询问其容量的唯一原因是了解系统的工作原理以及调试性能问题。

通常,您不必担心预留容量。重新分配很少是性能问题。 Swift使用(我相信)一个有效的重新分配计划,以便重新分配的数量在数组的最终计数中是对数的。例如。如果你一次添加一个百万个元素,Swift应该执行不超过20-30个重新分配。

但是,如果您知道您的阵列将非常大(例如,Mac上的千兆字节或iOS设备上的数十兆字节),或者您是在性能敏感的代码路径中填充阵列(例如填充音频缓冲区)这将在几微秒内开始播放),您可能希望保留容量并避免重新分配。

除非您知道重新分配是一个问题,否则您可能不应该担心保留容量,因为分析器显示它们是瓶颈或者因为您有其他证据(如音频缓冲区示例中的音频故障)。 / p>

答案 1 :(得分:4)

  

阵列容量有什么用?

基本上,阵列容量具有 no 外部使用。它适用于Swift的内部使用。如果您知道将为此阵列分配100个对象,那么可以在创建阵列时提前设置容量,并且我已经看到有些人在他们的代码中执行此操作;但是没有特定的需要这样做,并且没有特定的获得这样做。你已经看过引擎盖,看到了你真正不需要看的东西。现在你已经看过了,你可以忘掉它。

答案 2 :(得分:1)

不包含数组时数组可以包含的元素总数

分配新存储。

每个数组都保留特定数量的内存来容纳其内容。当您将元素添加到阵列中并且该阵列开始超出其保留容量时,该阵列会分配更大的内存区域并将其元素复制到新存储中。新存储是旧存储大小的倍数。这种指数增长策略意味着追加元素的时间恒定,从而平均了许多追加操作的性能。触发重新分配的追加操作会降低性能,但是随着阵列变大,它们的发生频率会越来越低。

下面的示例从数组文字创建整数数组,然后追加另一个集合的元素。在追加之前,数组会分配新的存储空间,该存储空间足以存储生成的元素。

var numbers = [10, 20, 30, 40, 50]

numbers.count == 5

numbers.capacity == 5

numbers.append(contentsOf: stride(from: 60, through: 100, by: 10))

numbers.count == 10

numbers.capacity == 12