Lesson content
Read, practise, then check your understanding
An iterator identifies a position in a range. A half-open range [first, last) includes first and excludes last, so an empty range has first == last. Dereferencing the end iterator is invalid.
#include <iostream>
#include <vector>
std::vector<int> values{2, 4, 6};
for (auto it = values.cbegin(); it != values.cend(); ++it) {
std::cout << *it << '\n';
}
Use begin/end for mutable traversal and cbegin/cend for read-only traversal. Range-for expands to iterator operations and is clearer when positions are unneeded.
Capabilities and adapters
Input iterators support single-pass reading, output iterators writing, forward iterators multipass traversal, bidirectional iterators decrement, and random-access iterators support arithmetic. Contiguous iterators additionally guarantee adjacent storage. Algorithms require only the weakest category they need.
std::back_inserter turns assignments into push_back; reverse iterators traverse backward; std::next, std::advance, and std::distance work across categories, though cost varies. C++20 ranges may use different iterator and sentinel types for an endpoint.
Iterators are non-owning and inherit container lifetime rules. Mutation can invalidate them: vector growth moves storage, erase invalidates defined regions, and unordered rehash changes bucket structure. Capture the iterator returned by erase when deleting during traversal. Never compare iterators from unrelated containers.
Knowledge check
Answer every question correctly to complete this chapter.
0 of 10 checks passed
Your progress is saved on this device.