Intermediate · The Standard Template Library (STL) · topic 21 of 42 · 30 min
std::vector in depth
Explanation
Why vector is the default container
The STL (Standard Template Library) is the part of the C++ standard library that gives you containers (things that hold elements) and algorithms (things that work on them). Among the containers, std::vector is the one you should reach for first. Its elements sit in one continuous block of memory, exactly like an array, which makes it very fast for the processor's cache (a small, very fast memory that loves data stored side by side).
Size and capacity
size() is how many elements the vector holds. capacity() is how many it could hold before it must get a bigger block of memory. When you push_back into a full vector, it allocates a bigger block (typically 1.5× or 2× the old capacity), moves the elements across and frees the old block. Because growth is geometric, the average cost of push_back stays constant: this is called amortised O(1).
#include <iostream>
#include <vector>
int main() {
std::vector<int> v;
for (int i = 0; i < 6; ++i) {
v.push_back(i);
std::cout << "size " << v.size() << " capacity " << v.capacity() << '\n';
}
std::vector<int> orders;
orders.reserve(100000); // one allocation up front when you know the size
}Common operations and their cost
| Operation | Example | Cost |
|---|---|---|
| Read/write by index | v[i], v.at(i) | O(1) |
| Add or remove at the end | push_back, emplace_back, pop_back | amortised O(1) |
| Insert or erase in the middle | v.insert(v.begin() + 2, x), v.erase(it) | O(n): later elements shift |
| Search for a value (unsorted) | std::find(v.begin(), v.end(), x) | O(n) |
| First / last element | v.front(), v.back() | O(1) (undefined if empty) |
O(1) means the time does not grow with the number of elements; O(n) means it grows in proportion to n. You will use this notation (Big-O) for the rest of the course.
emplace_back
struct Order { std::string item; int qty; };
std::vector<Order> cart;
cart.push_back(Order{"Rice", 2}); // builds an Order, then moves it in
cart.emplace_back("Dal", 1); // builds the Order directly inside the vectorIterator invalidation
Removing elements safely
std::vector<int> marks = {35, 80, 20, 90, 15};
// C++20: remove every value below 33
std::erase_if(marks, [](int m) { return m < 33; }); // marks is {80, 90}
// Before C++20: the erase-remove idiom
std::vector<int> v = {1, 0, 2, 0, 3};
v.erase(std::remove(v.begin(), v.end(), 0), v.end()); // v is {1, 2, 3}Other useful operations
- v.clear() removes all elements (capacity usually stays).
- v.resize(n) changes the size, adding default values or dropping elements.
- v.empty() is true when size() is 0; check it before front(), back() or v[0].
- v.data() gives a pointer to the first element, for C functions.
- Two vectors can be compared with == and < (element by element).
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
std::vector in depth · 1/6
std vector is the container you should use first. It stores elements side by side, like an array that grows.
Prefer a video by a teacher? Find free videos on “c++ std::vector size capacity reserve push_back iterator invalidation” on YouTube ↗
In real life: Collecting sensor readings
A factory machine sends a temperature reading every second, about 86,400 per day. The monitoring program reserves space for a day of readings, appends each one with push_back, and at midnight computes the maximum and clears the vector for the next day. One allocation per day instead of dozens.
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
std::vector<double> readings;
readings.reserve(86400);
for (int s = 0; s < 10; ++s) readings.push_back(60.0 + s % 4); // pretend data
double maxTemp = *std::max_element(readings.begin(), readings.end());
std::cout << "Max today: " << maxTemp << '\n'; // 63
readings.clear(); // capacity is kept for tomorrow
}Practice (0/4 done)
std::vector<int> v = {5, 6, 7}; v.pop_back(); v.push_back(9); What is v?
Which operation on a vector of n elements is O(n)?
Which line has the bug? 1: std::vector<int> v = {1, 2, 3}; 2: int* p = &v[0]; 3: for (int i = 0; i < 100; ++i) v.push_back(i); 4: std::cout << *p;
Read n exam marks into a vector. Remove all marks below 33 (fail), then print how many students passed and the marks in the original order. Use std::erase_if (C++20) or the erase-remove idiom.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- std::map and std::unordered_mapThe Standard Template Library (STL) · same module
- set, stack, queue, deque and priority_queueThe Standard Template Library (STL) · same module
- Iterators: the glue between containers and algorithmsThe Standard Template Library (STL) · same module
- realloc and growing arraysC Programming (from zero to systems) · Dynamic memory
- Space complexity and amortised costData Structures and Algorithms (DSA) for interviews · Thinking in Big-O
- Slices in depth: length, capacity and sharingGo Programming (backend and cloud) · Collections and structs
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
What does reserve(1000) change?
Answer: capacity() becomes at least 1000; size() stays the same
reserve only pre-allocates memory; it does not add elements.
Why is push_back called "amortised O(1)"?
Answer: Occasional reallocations are spread over many cheap pushes because capacity grows geometrically
Doubling (or 1.5×) growth keeps the average cost per push constant.
What does std::remove(v.begin(), v.end(), 0) do on its own?
Answer: Moves non-zero elements to the front and returns the new logical end; the size is unchanged
You must call erase with the returned iterator to actually shrink the vector.
Which container stores its elements in one continuous block of memory?
Answer: std::vector
vector (and array) are contiguous; list and map use separate nodes.
What is the main advantage of std::vector over a C-style array?Related
Answer: Its size can change at run time and it knows its size
vector grows with push_back and reports size(); it also manages its own memory.
What does it->first give for a std::map iterator?Related
Answer: The key
Map elements are pairs: first is the key, second is the value.
Starting from capacity 4 and doubling, what is the capacity after 9 pushes?Related
Why is list.append O(1) amortised and not O(1) every time?Related
Answer: Occasionally the list is full and must be copied to a bigger block
Most appends use spare room; a few trigger an O(n) copy. Averaged over many appends, the cost is O(1).
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 4 more topics in “The Standard Template Library (STL)” before its exam: std::map and std::unordered_map, set, stack, queue, deque and priority_queue, Iterators: the glue between containers and algorithms, STL algorithms: sort, find, count, accumulate and binary search.
- Module 6 exam: The STL · 13 questions · 25 min, without help. 5 topics of this module still to finish first.
- Then the next module, Templates, smart pointers and move semantics. 42 topics left in the course before the final exam.
← Previous: Abstract classes, interfaces and good class design