C++ vectors and iterator invalidation
Grow a dynamic array and use checked access.
On this page
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
#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);
}2 5 6
Follow the code
Open the walkthrough to inspect the example one step at a time.
Show guided walkthrough
#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);}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
| Step / line | What happens | State after step | Output 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.