Concepts / Iterator Operations and Their Meanings

Iterator Operations and Their Meanings

An iterator is defined by its semantics and the naming of its operations, not by one fixed type. Any object that obeys the rules is an iterator.

  • Programming

Why Loops Need a Pointer

Suppose you are writing a loop that walks through a collection of records. You need some way to point at one record, move on to the next one, and read the record you are pointing at. The language gives you a tool for exactly this job, and it is called an iterator.

A natural first question is which specific iterator type you should write down. The answer this article builds toward is that, for most day-to-day work, you do not need to know it. What you need to know is how iterators behave, and where to find the name when you do need it.

An Iterator as a Role

Think of an iterator less as a particular kind of thing and more as a role that many different objects can play. What makes an object an iterator is that it responds to the same operations in the same way. The operations are named consistently across all iterators, and their meanings are shared. Whatever the underlying object looks like, if it honors these shared meanings, it counts as an iterator.

Definition

An iterator is defined by its semantics and the naming of its operations, not by one fixed type. Any object that obeys the rules is an iterator.

This is why the idea of a single iterator type can be misleading. Two different objects can have different concrete types and still both be iterators, because they both support the same operations with the same meanings. The thing you are learning is the shared behavior, not the internal shape of any one object.

Tracing an Iterator Through a List

The clearest way to see the shared behavior is to follow an iterator step by step. Imagine a list holding three names, in order: Ada, Grace, and Alan. Picture an iterator that starts out referring to Ada.

Adawhere the iterator startsGraceafter one ++, dereferencegives GraceAlanafter a second ++++++
After applying ++ to an iterator, which element does dereferencing it now refer to, and how does each step move the position along the sequence?

Read the diagram from left to right. Each arrow is one application of the increment operator. The position of the iterator moves along the list one element at a time: first from Ada to Grace, then from Grace to Alan. At every point, the element you would get by dereferencing the iterator is the element it currently refers to, not the element it used to refer to.

What do you think happens?

The iterator starts at Ada. You apply the increment operator once, then apply the dereference operator. What do you get?

  • Ada

  • Grace

  • Alan

Reveal answer
Answer:

Grace

Increment moves the iterator to the next element, which is Grace. Dereferencing then reads the element the iterator now refers to, so the result is Grace.

Increment Moves and Dereference Reads

The two core operations pull in different directions. The increment operator changes which element the iterator points to, moving it forward to the next one. Applying it yields an iterator that refers to the next element.

The dereference operator does not move anything. It reads through the iterator and gives you the element currently being referred to. Applying it yields the element to which the iterator refers, and the iterator itself stays exactly where it was.

Container-Owned Iterator Names

If iterators are defined by shared behavior, you might expect every program to name a separate iterator type for every container it uses. The source describes a convenience instead. Each container knows the iterator types that belong to it, and it makes those types available under two conventional names: iterator and const_iterator.

list<Entry>the container that owns thetypesiteratorconventional name for itsiterator typeconst_iteratorconventional name for itsconst iterator typeexposesexposes
How does a container expose its iterator and const_iterator types, and which container owns each nested type name?

The container is the one that owns and advertises these types. That means you look the name up through the container rather than memorizing a separate name for each collection. If you have a list of Entry values, the iterator type you need is found through that list, not invented from scratch.

This article concentrates on the naming. How the two names differ in what they permit is a separate question and is not settled by the material covered here, so do not infer more from the names than the source states.

Reading list<Entry>::iterator

A qualified name such as list<Entry>::iterator identifies the general iterator type of that container. You rarely need to know how that type is defined, but you should be able to read the name and say what it refers to.

listthe container<Entry>the element type the listholds::reaches a name inside thecontaineriteratorthe iterator type nested inlist
In list<Entry>::iterator, which part names the container, which part names the element type, and which part names the iterator type nested inside the container?

Read the name from left to right. The part before the double colon names the container and the element type it holds. The part after the double colon names the iterator type that belongs to that container. So list<Entry>::iterator means the iterator type of a list whose elements are Entry values.

Mistakes Beginners Make

  • Common mistake

    Believing there is one iterator type that every container uses

    Why it fails

    An iterator is defined by shared behavior and operation names, so different objects with different concrete types can all be iterators.

    Do this instead

    Think of iterator as a role. Ask whether an object honors the shared operations, not whether it matches one fixed type.

  • Common mistake

    Expecting dereferencing to move the iterator

    What it looks like

    After dereferencing an iterator that refers to Ada, you assume it now refers to Grace.

    Why it fails

    The dereference operator does not move anything. It only reads the element currently referred to.

    Do this instead

    Use the increment operator to move forward, then dereference to read the new position.

  • Common mistake

    Trying to memorize a separate iterator name for every collection

    Why it fails

    Each container owns its iterator types and advertises them under the conventional names iterator and const_iterator.

    Do this instead

    Look the name up through the container, for example by reading the qualified name list<Entry>::iterator.

  • Common mistake

    Reading list<Entry>::iterator as a single word instead of splitting it at the double colon

Tracing Your Own Iterator

Here is a different list, generated for practice, holding three colors in order: red, green, and blue. Suppose an iterator starts out referring to red. Work through the following steps before checking the answers.

EASY

Starting from red, apply the increment operator twice. Which element does the iterator refer to now, and what does dereferencing it return?

Hints
  • Each application of the increment operator moves the iterator one element forward.
  • After two increments from red you have moved past green.
  • Dereferencing reads the element the iterator refers to and does not move it.

The answer is blue. The first increment moves the iterator from red to green, and the second moves it from green to blue. Dereferencing then returns blue, and the iterator still refers to blue because dereferencing does not move it.

Key Takeaways

  • An iterator is defined by its semantics and the naming of its operations, so any object that obeys the shared rules counts as an iterator.
  • The increment operator moves an iterator forward to the next element, while the dereference operator reads the element the iterator currently refers to without moving it.
  • Each container owns its iterator types and makes them available under the conventional names iterator and const_iterator, so you look them up through the container.
  • In a qualified name such as list<Entry>::iterator, the part before the double colon names the container and its element type, and the part after it names the iterator type nested inside that container.

Related concepts

More concepts starting with I