Iterators in C++ STL
An iterator is an object that points to an element inside a container — like a vector, list, map, or set. You use iterators to move through a container element by element, read values, modify them, or pass ranges to STL algorithms.
Think of an iterator like a bookmark in a book. The bookmark points to a specific page (element). You can move it forward or backward to visit other pages, and you can read or change the content at the current page.
Why Iterators Exist
Different containers store data differently. A vector stores elements in a contiguous array; a list stores them as linked nodes; a map stores them as a tree. Each has a completely different internal layout. Iterators provide a uniform interface to traverse all of them with the same syntax.
┌────────────────────────────────────────────────────────────┐
│ Without iterators: different access method per container │
│ vector: arr[i] list: traverse links │
│ │
│ With iterators: same syntax for every container │
│ for (auto it = c.begin(); it != c.end(); ++it) { ... } │
└────────────────────────────────────────────────────────────┘
begin() and end()
Every STL container provides two key iterator functions:
begin()— returns an iterator pointing to the first element.end()— returns an iterator pointing one past the last element (not the last element itself — do not dereference it).
Vector: [10][20][30][40]
↑ ↑
begin() end() ← points here (past the last)
Basic Iterator Example with Vector
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v = {10, 20, 30, 40, 50};
vector<int>::iterator it;
for (it = v.begin(); it != v.end(); ++it) {
cout << *it << " "; // dereference to get value
}
cout << endl;
return 0;
}
Output:
10 20 30 40 50
The *it dereference operator reads the value the iterator currently points to. The ++it moves the iterator to the next element.
Using auto to Simplify Iterator Syntax
Writing vector<int>::iterator is long. The auto keyword makes it short and readable.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v = {10, 20, 30, 40, 50};
for (auto it = v.begin(); it != v.end(); ++it) {
cout << *it << " ";
}
cout << endl;
return 0;
}
Output:
10 20 30 40 50
Types of Iterators
┌────────────────────────┬────────────────────────────────────────────────┐
│ Iterator Type │ Description │
├────────────────────────┼────────────────────────────────────────────────┤
│ Input iterator │ Read only, move forward once │
│ Output iterator │ Write only, move forward once │
│ Forward iterator │ Read/write, move forward (one pass) │
│ Bidirectional iterator │ Read/write, move forward AND backward │
│ Random access iterator │ Read/write, jump to any position directly │
└────────────────────────┴────────────────────────────────────────────────┘
Container support:
vector, deque → Random access iterator (fastest)
list → Bidirectional iterator
set, map → Bidirectional iterator
unordered_map → Forward iterator
Modifying Elements Through an Iterator
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v = {1, 2, 3, 4, 5};
for (auto it = v.begin(); it != v.end(); ++it) {
*it *= 10; // multiply each element by 10
}
for (auto n : v) {
cout << n << " ";
}
cout << endl;
return 0;
}
Output:
10 20 30 40 50
Reverse Iterators
Use rbegin() and rend() to traverse a container in reverse order.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v = {10, 20, 30, 40, 50};
cout << "Reverse order: ";
for (auto it = v.rbegin(); it != v.rend(); ++it) {
cout << *it << " ";
}
cout << endl;
return 0;
}
Output:
Reverse order: 50 40 30 20 10
Const Iterators
Use cbegin() and cend() when you want to read elements without modifying them. Trying to modify through a const iterator causes a compile error.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v = {5, 10, 15};
for (auto it = v.cbegin(); it != v.cend(); ++it) {
cout << *it << " ";
// *it = 99; // ERROR: cannot modify through const_iterator
}
cout << endl;
return 0;
}
Random Access with Vector Iterator
Vector iterators support arithmetic — you can jump ahead by any number of positions.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v = {10, 20, 30, 40, 50};
auto it = v.begin();
cout << "First element: " << *it << endl;
it += 2;
cout << "Third element: " << *it << endl;
it--;
cout << "Second element: " << *it << endl;
cout << "Distance from begin to it: " << (it - v.begin()) << endl;
return 0;
}
Output:
First element: 10
Third element: 30
Second element: 20
Distance from begin to it: 1
Iterators with a Map
#include <iostream>
#include <map>
using namespace std;
int main() {
map<string, int> age = {{"Alice", 25}, {"Bob", 30}, {"Carol", 28}};
for (auto it = age.begin(); it != age.end(); ++it) {
cout << it->first << " is " << it->second << " years old." << endl;
}
return 0;
}
Output:
Alice is 25 years old.
Bob is 30 years old.
Carol is 28 years old.
For map iterators, it->first accesses the key and it->second accesses the value.
Iterator with STL Algorithms
STL algorithms like find, sort, and count all use iterators to work with containers.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> v = {40, 10, 30, 20, 50};
auto it = find(v.begin(), v.end(), 30);
if (it != v.end()) {
cout << "Found 30 at position: " << (it - v.begin()) << endl;
}
sort(v.begin(), v.end());
for (auto n : v) cout << n << " ";
cout << endl;
return 0;
}
Output:
Found 30 at position: 2
10 20 30 40 50
Iterator Summary
| Function | Returns |
|---|---|
begin() | Iterator to first element |
end() | Iterator one past last element |
rbegin() | Reverse iterator to last element |
rend() | Reverse iterator one before first element |
cbegin() | Const iterator to first element |
cend() | Const iterator one past last element |
Key Takeaways
- Iterators are objects that point to elements inside STL containers.
begin()points to the first element;end()points one past the last — never dereferenceend().- Use
*itto read a value and++itto advance the iterator. - Use
autoto avoid writing long iterator type names. - Reverse iterators (
rbegin(),rend()) traverse containers backwards. - Const iterators (
cbegin(),cend()) allow reading without modification.
