How does an Array grow, and when do reserveCapacity and ContiguousArray help?
Predict first
What does this print?
var a = [Int]()
a.reserveCapacity(100)
print(a.count, a.capacity >= 100)
- 0 true
- 100 true
- 0 false
Predict first
What does this print?
var a = Array(repeating: 0, count: 100)
a.removeAll(keepingCapacity: true)
print(a.count, a.capacity >= 100)
- 0 true
- 0 false
Mental model. Appending is moving to a bigger house each time you outgrow the last. Doubling the size means you move rarely.
An array stores elements in one heap buffer. When an append would overflow it, the array allocates a larger buffer (roughly doubling) and moves the elements over. Doubling is why append is O(1) amortised: occasional O(n) copies spread across many cheap appends.
If you know the final size, reserveCapacity(_:) allocates once up front and skips the repeated growth. removeAll(keepingCapacity: true) empties the array but keeps the buffer for reuse. ContiguousArray guarantees native contiguous storage; a plain Array of class types can be backed by an NSArray on Apple platforms, which adds a check on access.
Reserving makes room but adds no elements. capacity is at least what you asked for.
The elements go, the buffer stays. That is the point of keepingCapacity: reuse the allocation next time.
Common traps
- “
capacityis the exact size I asked for.” It is a lower bound. The runtime may give you more. - Reserving in a loop that also removes. Reserve once, before filling. It does not make later growth impossible.
They might follow up with
- Does
reserveCapacitychangecount? No. Capacity is spare room; count is how many elements exist. - When is
ContiguousArrayworth it? For class element types on hot paths, where the bridging check shows up in a profile.
Related questions
- 2.1.3 When is the standard library not enough, and what does swift-collections add?
- 2.9.3 What does bridging cost, and where does it show up in a profile?
← When is the standard library not enough, and what does… What happens if you mutate an array while you loop over it? →