Dataslope logoDataslope

Arrays and std::vector

Learn fixed arrays, std::array, std::vector, contiguous memory, iteration, capacity, and matrix-style storage in C++

Arrays are the first data structure most programmers meet: a sequence of values stored side by side. In modern C++, the array you will use most is std::vector<T> because it grows dynamically while keeping fast O(1) indexing.

C-style arrays

A C-style array such as int a[5] has a fixed size known at compile time. It is compact and fast, but it loses size information easily because it decays to a pointer when passed to many functions.

Code Block
C++ 20 (202002L)

You almost never want raw arrays for DSA practice because std::array and std::vector are safer and more expressive.

std::array<T, N>

std::array is a fixed-size array wrapper. It preserves the size, supports range-for loops, and behaves like a normal value object.

Code Block
C++ 20 (202002L)

std::vector<T>: the workhorse

std::vector is a dynamic array. It stores elements contiguously like an array, but it can allocate a larger block and move elements when it needs more capacity.

Code Block
C++ 20 (202002L)

Use operator[] when you know the index is valid. Use .at() when you want bounds checking and an exception on invalid access.

Contiguous memory layout

A vector keeps values next to each other in memory. That makes iteration cache-friendly: when the CPU loads one element, nearby elements are likely pulled into cache too.

Code Block
C++ 20 (202002L)

The printed addresses should increase by sizeof(int) each time in a normal implementation.

Iteration patterns

Index-based loops are useful when you need positions. Range-for loops are clean when you only need values. Iterators are the common language of STL algorithms.

Code Block
C++ 20 (202002L)

Resizing, capacity, and amortized push

size() is how many elements are currently stored. capacity() is how many elements fit before reallocation. When capacity is full, a vector usually grows by allocating a larger buffer, often about double the old capacity.

Code Block
C++ 20 (202002L)

That rare reallocation is why push_back is O(1) amortized, as discussed in the complexity page.

Timing one million pushes

Browser timing is noisy, but this shows how to measure a sequence of pushes with <chrono>.

Code Block
C++ 20 (202002L)

2D vectors

A matrix is often represented as std::vector<std::vector<int>>: a vector of rows, where each row is another vector.

Code Block
C++ 20 (202002L)

Vector operation costs

OperationComplexityWhy
v[i], v.at(i)O(1)Direct address calculation
push_backO(1) amortizedRare reallocations are spread over many pushes
insert in middleO(n)Elements after the position shift right
erase from middleO(n)Elements after the position shift left

Practice: reverse a vector in-place

Challenge
C++ 20 (202002L)
Reverse a vector in-place

Implement reverseInPlace without using std::reverse. Swap from both ends until the pointers meet.

Practice: second-largest value

Challenge
C++ 20 (202002L)
Find the second-largest value

Implement secondLargest in one pass without sorting. Keep the best value and the runner-up as you scan.

Check your understanding

QuestionSelect one

Why does iterating through a std::vector<int> often run faster than iterating through a linked list with the same number of integers?

The vector stores elements contiguously, which improves cache locality.

A vector changes every operation to O(log n).

A linked list cannot store integers.

A vector never reallocates memory.

QuestionSelect one

For most DSA problems, why should you usually try std::vector before std::list?

std::list has O(1) random access.

std::vector has compact storage, O(1) indexing, and excellent iteration performance.

std::vector can only store primitive types.

std::list is always asymptotically slower for every operation.

QuestionSelect one

What is the main behavioral difference between v.at(i) and v[i] for a std::vector?

v.at(i) is always O(n), while v[i] is O(1).

v[i] checks bounds and throws if invalid.

v.at(i) performs bounds checking and throws an exception when i is invalid.

v.at(i) inserts a new element if i is too large.

On this page