STL · Data structures

Vectors

Distinguish existing elements, spare storage, and invalidated addresses.

A sequence with room to grow.

A std::vector<int> stores a growable sequence of integers contiguously. Size counts existing elements. Capacity counts how many elements the current storage can hold before an append needs new storage. Spare capacity is room for future elements, not additional elements you may already index.

Spare storage avoids allocating on every append.

reserve asks for enough capacity without changing size. resize changes the number of elements. Reserving ahead can reduce reallocations, but it does not make an out-of-range subscript valid. To create another element, use an operation such as push_back or resize.

Reserving does not create elements.

The vector begins with two elements. reserve(8) ensures capacity is at least 8 without changing that count. push_back creates the third element, so the final size is 3.

std::vector<int> values{10, 20};
values.reserve(8);
values.push_back(30);
std::cout << values.size(); // 3

Only the first size slots are elements.

The first three positions contain live integers. The remaining capacity is available storage. The exact capacity after reserve(8) may be greater than eight; only the minimum is guaranteed.

Three existing values, 10, 20, 30, followed by spare capacity. Size is 3; capacity is at least 8.
[0] 10
element
[1] 20
element
[2] 30
element
spare storage
not elements yet

Reallocation moves the elements to new storage.

An append that reallocates invalidates old pointers and references to elements. An append with spare capacity preserves existing element addresses, though the old end iterator is invalidated. After an operation that may reallocate, obtain a fresh pointer or iterator before using it.

Further reading

Trusted resources for the rules and APIs discussed in this guide.