C++ · Course navigation

C++ vectors and iterator invalidation

Grow a dynamic array and use checked access.

On this page
Before you start

Loops and standard-library containers.

  • Grow a dynamic array and use checked access.
  • Predict the sample output and explain the state changes.
  • Complete the practice task and check the boundary cases.

The concept

A vector stores elements contiguously and grows as needed. push_back appends; at performs bounds checking and throws out_of_range for an invalid index.

Growth can reallocate the underlying storage, invalidating pointers, references, and iterators into it. This program reads elements only after appending.

Code example

C++
#include <iostream>
#include <vector>
#include <cassert>
int main() {
    std::vector<int> values{2, 4};
    values.push_back(6);
    values.at(1) = 5;
    for (int value : values) std::cout << value << '\n';
    assert(values.size() == 3);
}
Output
2
5
6

Follow the code

Open the walkthrough to inspect the example one step at a time.

Show guided walkthrough
Guided walkthroughReady
1#include <iostream>
2#include <vector>
3#include <cassert>
4int main() {
5 std::vector<int> values{2, 4};
6 values.push_back(6);
7 values.at(1) = 5;
8 for (int value : values) std::cout << value << '\n';
9 assert(values.size() == 3);
10}

Follow the example

Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.

View the complete dry-run table
Prepared trace of the published program. Some rows group repeated iterations.
Step / lineWhat happensState after stepOutput so far
Construct two elements.values = [2, 4]
—
Append, potentially reallocating storage.values = [2, 4, 6]
—
Replace the second element through checked access.values = [2, 5, 6]
—
Visit and print all three elements.values = [2, 5, 6]
2
5
6

Behind the scenes

How C++ processes this code

The C++ compiler produces a native executable. Execution enters main, where objects and function calls perform the work.

Cost and common mistakes

O(1) indexed access; amortized O(1) append, O(n) if append reallocates; O(n) traversal and storage.

  • operator[] does not provide the bounds check of at.
  • Do not retain an iterator across an operation that invalidates it.

Try it yourself

What does values.at(3) do after these operations?

Reveal answer and reasoning

It throws std::out_of_range because valid indices are 0, 1, and 2.

Further reading