Iterators & Iterator Categories
ইটারেটর ও তাদের ক্যাটাগরি
1. What Is an Iterator?
An iterator is a generalized pointer. It supports *, ++, and (depending on category) more.
#include <iostream>
#include <vector>
#include <list>
int main() {
std::vector<int> v = {10, 20, 30};
for (auto it = v.begin(); it != v.end(); ++it) {
std::cout << *it << " ";
}
std::cout << "\n";
// Same pattern works for std::list
std::list<int> L = {1, 2, 3};
for (auto it = L.begin(); it != L.end(); ++it)
std::cout << *it << " ";
}
2. The Six Categories
| Category | Operations | Example |
|---|---|---|
| Input | ++ * == (read-once) | std::istream_iterator |
| Output | ++ * (write-once) | std::ostream_iterator |
| Forward | Input + multi-pass | std::forward_list |
| Bidirectional | Forward + -- | std::list, std::map |
| Random Access | Bidirectional + + - [i] | std::vector, std::deque |
| Contiguous (C++20) | Random + memory contiguous | std::vector, raw arrays |
3. begin(), end() & Reverse Iterators
#include <iostream>
#include <vector>
int main() {
std::vector<int> v = {1, 2, 3, 4, 5};
// reverse iteration
for (auto it = v.rbegin(); it != v.rend(); ++it)
std::cout << *it << " ";
std::cout << "\n";
// const iteration
for (auto it = v.cbegin(); it != v.cend(); ++it)
std::cout << *it << " ";
}
4. Iterator Invalidation
| Container | What invalidates |
|---|---|
| vector | Reallocation invalidates all; insert/erase invalidates from that point on |
| deque | Insert at middle invalidates everything; at ends, only iterators |
| list / forward_list | Only invalidates the erased iterator |
| map / set | Only the erased iterator |
| unordered_map / set | Rehashing invalidates iterators (not references) |
5. Common Iterator Operations
std::next(it, n)/std::prev(it, n)std::distance(a, b)— number of steps from a to bstd::advance(it, n)— move iterator
6. Practice Problems
- Iterate a vector with iterators (not range-for).
✨ Show Answer
See section 1.
- Why does
v.end()point past the last element?✨ Show Answer
Half-open range convention
[begin, end). Letsend - beginequal size, and lets empty ranges bebegin == end. - Print elements in reverse using rbegin/rend.
✨ Show Answer
See section 3.
- Why use
cbegin/cend?✨ Show Answer
Returns a const_iterator regardless of the variable's constness. Useful for safety in templates.
- What category is std::list iterator?
✨ Show Answer
Bidirectional.
++and--work, but no randomit + 5. - Why does
std::sortrequire random-access iterators?✨ Show Answer
Quicksort partitions need to swap elements at arbitrary positions in O(1). Lists can't do this efficiently — they have
list::sortinstead. - Compute distance between two iterators.
✨ Show Answer
auto n = std::distance(it1, it2); - Advance an iterator by 3.
✨ Show Answer
std::advance(it, 3); // or auto j = std::next(it, 3); - Erase elements while iterating safely.
✨ Show Answer
for (auto it = v.begin(); it != v.end(); ) { if (*it < 0) it = v.erase(it); // erase returns next valid else ++it; } - Use ostream_iterator to print.
✨ Show Answer
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " ")); - When does push_back invalidate vector iterators?
✨ Show Answer
When it triggers a reallocation (size exceeds capacity). All previous iterators are invalidated.
- Build a list iterator iterating from end.
✨ Show Answer
for (auto it = L.rbegin(); it != L.rend(); ++it) ... - What's a const_iterator vs iterator?
✨ Show Answer
const_iterator gives read-only access (
*itis const). Use it when you don't need to modify. - Why does
v.begin() + 1work but not on list?✨ Show Answer
Vector iterators are random-access; arithmetic is O(1). List iterators are bidirectional; you can only
++/--in O(1).
Summary
Iterators are the bridge between containers and algorithms. Six categories define what operations they support. Use range-for for simple iteration; use raw iterators when you need to erase, insert, or pass to STL algorithms. Always know your iterator invalidation rules — they cause subtle bugs.