Container Iterator Names
The defining feature of an iterator is behavior, not membership in one specific class. If an object supports ++ so that the result refers to the next element, and * so that it yields the element being referred to, it counts as an iterator.
Why Different Collections Look Alike
Suppose you have a collection of items and you want to visit each one in turn. Many different kinds of collections exist, and each may store its items in a different way. Yet when you look at the tools used to move through them, a surprising pattern appears. The tools look alike. The same operations keep showing up, and they mean the same things no matter which collection they came from. That shared behavior is what makes a family of objects called iterators.
The question this article answers is simple: what do all iterators have in common? The short answer is their semantics, meaning what their operations do, and the naming of those operations. Once you understand those two things, you can work with iterators from many different containers without relearning the rules each time.
What do you think happens?
If an iterator refers to the first element of a sequence and you apply ++ to it once, what does the result refer to?
Reveal answer
The next element in the sequence, the one after the first.
Applying ++ to any iterator produces an iterator that refers to the next element in the sequence. The result is itself an iterator, so you can keep applying ++ to keep moving forward.
The Two Shared Operations
An iterator is tied to two operations that capture almost everything you do with one. The first is the increment operation, written ++. Applying ++ to any iterator produces an iterator that refers to the next element in the sequence. The result is itself an iterator, so the operation can be repeated to keep moving forward.
The second is the dereference operation, written with the asterisk, *. Applying * to an iterator yields the element to which that iterator refers. Where ++ answers the question of where to go next, * answers the question of what is currently being pointed at.
The diagram uses a short list of three made-up items. Each arrow labeled ++ moves the iterator one step forward to the next element. At every position, * is the operation that reads the element the iterator currently points at. The two operations divide the work cleanly: ++ changes which element is referred to, and * retrieves that element.
Tracing an Iterator Step by Step
A good way to see the two operations work together is to trace an iterator through a short sequence and record, after each step, where it refers and what * would return. The example below uses the same three made-up items as the previous diagram.
Tracing an iterator through a three-element sequence
A sequence holds apple, banana, and cherry in that order. An iterator starts by referring to apple. Apply ++, read with *, then apply ++ again and read with *. What does the iterator refer to at each stage?
- 1Start
The iterator refers to apple. Applying * yields apple, the element to which the iterator refers.
- 2After the first ++
Applying ++ produces an iterator that refers to the next element, banana. Applying * to this new iterator yields banana.
- 3After the second ++
Applying ++ again moves the iterator to the next element after banana, which is cherry. Applying * yields cherry.
The iterator visits apple, then banana, then cherry. Each ++ moves the iterator forward one element, and each * reads the element at the current position.
Watching the Position Change
The before and after view makes the change explicit. Before ++ is applied, the iterator refers to banana. After ++ is applied, the iterator refers to cherry. The iterator itself is what changes position, while the sequence of elements stays the same.
Why Behavior Defines an Iterator
A natural first guess is that an iterator must belong to some special family of classes, with a required parent and a fixed structure. The source takes a different view. What makes an object an iterator is that it obeys a few simple rules, such as the ones for ++ and *. Any object that follows rules like these is an iterator.
The defining feature of an iterator is behavior, not membership in one specific class. If an object supports ++ so that the result refers to the next element, and * so that it yields the element being referred to, it counts as an iterator.
This is why the same tools can be used across many different containers. The rules stay the same even when the way each collection stores its items is different. You can rely on the shared meaning of ++ and * rather than on the details of any single container.
Reading the Conventional Iterator Names
Containers make their iterator types available under the conventional names iterator and const_iterator. The source gives one concrete example: the general iterator type for a list of Entry elements is written list<Entry>::iterator. The name combines the container type, list<Entry>, with the conventional member name iterator. Reading the name this way tells you which container the iterator belongs to, even when you do not know anything else about its definition.
| Name | How you reach it | What the source states |
|---|---|---|
| iterator | Through the container, as in list<Entry>::iterator | Conventional name for the container's iterator type |
| const_iterator | Through the container, using the same naming pattern | Conventional name listed alongside iterator; the source does not give further rules for it here |
The two conventional iterator names each are reached through the container that owns them.
Why the Internal Definition Rarely Matters
Most of the time you do not need to know the exact type of a particular iterator. Each container knows which iterator types belong to it, and it makes them available under conventional names. You reach the type through the container, not by memorizing a separate name for each one.
Programmers usually do not need the internal definition of an iterator type. They can rely on the shared semantics of ++ and * and on the conventional naming. This means that code written against those shared rules can work with iterators from different containers without knowing how each one is built inside.
Mistakes Learners Make with Iterator Names
Common mistake Believing an iterator must be a pointer or belong to one specific class
Why it failsThe source states that what makes an object an iterator is that it obeys simple rules for ++ and *. Membership in a particular family is not the test.
Do this insteadAsk whether the object supports ++ moving to the next element and * yielding the element it refers to.
Common mistake Thinking ++ changes the element stored in the sequence
Why it failsApplying ++ produces an iterator that refers to the next element. The elements stay where they are; the iterator's position changes.
Do this insteadTrack the iterator's position separately from the elements it refers to.
Common mistake Assuming * and ++ mean the same thing
Why it failsThe source separates them: ++ answers where to go next, and * answers what is currently being pointed at.
Do this insteadUse ++ to move and * to read the current element.
Common mistake Memorizing a separate name for every iterator type
Why it failsContainers expose their iterator types under the conventional names iterator and
const_iterator, so the name is reached through the container.Do this insteadRead names like list<Entry>::iterator as the container plus the conventional member name.
Checking Your Understanding
An iterator refers to cherry in the sequence apple, banana, cherry. You apply ++ and then read the result with *. Which element do you get, and why? Then explain in one sentence why the list of elements itself did not change.
Hints
- Recall that ++ produces an iterator that refers to the next element.
- Recall that * yields the element to which the iterator refers.
- The iterator moves; the sequence of stored elements stays the same.
Key Takeaways
- Every iterator supports two shared operations: ++ yields an iterator that refers to the next element, and * yields the element to which the iterator refers.
- An object counts as an iterator because it obeys simple rules for these operations, not because it belongs to a special class or family.
- Containers expose their iterator types under the conventional names iterator and
const_iterator, reached through the container as in list<Entry>::iterator. - Programmers usually do not need the internal definition of an iterator type and can rely on the shared semantics and naming.