Iterators & Iterator Categories

ইটারেটর ও তাদের ক্যাটাগরি

Read: ~30 min 14 practice problems

1. What Is an Iterator?

An iterator is a generalized pointer. It supports *, ++, and (depending on category) more.

iter.cpp
#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

CategoryOperationsExample
Input++ * == (read-once)std::istream_iterator
Output++ * (write-once)std::ostream_iterator
ForwardInput + multi-passstd::forward_list
BidirectionalForward + --std::list, std::map
Random AccessBidirectional + + - [i]std::vector, std::deque
Contiguous (C++20)Random + memory contiguousstd::vector, raw arrays

3. begin(), end() & Reverse Iterators

reverse.cpp
#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

ContainerWhat invalidates
vectorReallocation invalidates all; insert/erase invalidates from that point on
dequeInsert at middle invalidates everything; at ends, only iterators
list / forward_listOnly invalidates the erased iterator
map / setOnly the erased iterator
unordered_map / setRehashing invalidates iterators (not references)
Common bug Iterating with one iterator while modifying the container with another. Always check invalidation rules.

5. Common Iterator Operations

  • std::next(it, n) / std::prev(it, n)
  • std::distance(a, b) — number of steps from a to b
  • std::advance(it, n) — move iterator

6. Practice Problems

  1. Iterate a vector with iterators (not range-for).
    ✨ Show Answer

    See section 1.

  2. Why does v.end() point past the last element?
    ✨ Show Answer

    Half-open range convention [begin, end). Lets end - begin equal size, and lets empty ranges be begin == end.

  3. Print elements in reverse using rbegin/rend.
    ✨ Show Answer

    See section 3.

  4. Why use cbegin/cend?
    ✨ Show Answer

    Returns a const_iterator regardless of the variable's constness. Useful for safety in templates.

  5. What category is std::list iterator?
    ✨ Show Answer

    Bidirectional. ++ and -- work, but no random it + 5.

  6. Why does std::sort require 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::sort instead.

  7. Compute distance between two iterators.
    ✨ Show Answer
    auto n = std::distance(it1, it2);
  8. Advance an iterator by 3.
    ✨ Show Answer
    std::advance(it, 3); // or auto j = std::next(it, 3);
  9. 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;
    }
  10. Use ostream_iterator to print.
    ✨ Show Answer
    std::copy(v.begin(), v.end(),
        std::ostream_iterator<int>(std::cout, " "));
  11. When does push_back invalidate vector iterators?
    ✨ Show Answer

    When it triggers a reallocation (size exceeds capacity). All previous iterators are invalidated.

  12. Build a list iterator iterating from end.
    ✨ Show Answer
    for (auto it = L.rbegin(); it != L.rend(); ++it) ...
  13. What's a const_iterator vs iterator?
    ✨ Show Answer

    const_iterator gives read-only access (*it is const). Use it when you don't need to modify.

  14. Why does v.begin() + 1 work 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.

Next Module → Lambda Expressions & std::function.