ProgrammingC++ Developer

What are iterators in C++ STL, what types exist, and what nuances of their usage should be known when programming?

Pass interviews with Hintsage AI assistant

Answer

Iterators are objects that allow referencing elements of STL containers similarly to pointers. They provide a uniform way to access elements of any container (vector, list, map, etc.). There are several types of iterators:

  • InputIterator — for reading a sequence forward.
  • OutputIterator — for writing values to a sequence.
  • ForwardIterator — for reading and writing forward (lives longer than OutputIterator).
  • BidirectionalIterator — allows movement both forward and backward.
  • RandomAccessIterator — supports random access (e.g., std::vector::iterator).

Special attention should be given to the lifetime of iterators:

  • Container iterators can become invalid when the container is modified. For example, inserting elements into a vector can invalidate old iterators.
  • Different containers manage the lifecycle of iterators differently. In std::list, insertions or deletions do not invalidate other iterators, while in std::vector, they almost always do.

Example:

std::vector<int> v = {1,2,3,4,5}; for (auto it = v.begin(); it != v.end(); ++it) { if (*it == 3) { // Remove the element with the value 3 it = v.erase(it); // erase returns an iterator to the next element --it; // correct the iterator if necessary } }

Trick Question

Question: When calling std::vector::insert, do the iterators get invalidated?
Common Answer: No, only when adding outside the end range.
Correct Answer: All iterators and references equal to or following the insertion position become invalid if the container's capacity is increased. If the capacity is sufficient — only the iterators in the range after the insertion point become invalid.

Example:

std::vector<int> v = {1,2,3}; auto it = v.begin() + 1; v.insert(v.begin(), 0); // it may be invalidated here!

Examples of real errors due to ignorance of the topic nuances


Story: In a project, pointers were used to iterate over std::vector, and after push_back, the iteration continued over invalidated pointers, leading to application crashes.



Story: A developer deleted elements from std::list through erase in a for(auto it : list) loop without using the returned erase iterator, causing the iteration to skip elements and not delete all intended ones.



Story: The code used std::map, and after erase by key, the iterator remained tied to the deleted element (undefined behavior) — this led to random crashes during further accesses.