Working with Iterators
Iterators can be obtained in two ways: directly from a container when you first encounter it, and as the return value of an algorithm.
Why Iterators Need a Starting Point
An iterator is only useful if you can get hold of one. Before you can walk through the elements of a collection, or work with one particular element, you need an iterator that refers to that element. This section answers a single question: where do iterators come from?
The answer is that iterators come from two situations. The first is when you first encounter a container. The second is when you call an algorithm. Keep these two sources in mind as you read, because the rest of this section examines each one in turn.
Getting an Iterator from a Container
The first source is the container itself. When you first encounter a container, you can obtain iterators directly from it. The source gives begin() and end() as its examples of this kind of iterator.
The wording the source uses is precise. These iterators refer to useful elements. The point is not that a container hands you a copy of its contents. Instead, the container hands you iterators that point into it. Any later work you do with those iterators is work on the container's own elements.
The diagram is a schematic and is not a full specification. The source names begin() and end() as the examples to learn from, and it does not spell out their exact positions. Treat the boundary placement of end() as something to confirm when you study the container's elements in detail. What this section establishes is the shape of the exchange: the container gives you an iterator, and that iterator is what you use next.
Getting an Iterator from an Algorithm
The second source is the return value of an algorithm. The standard algorithm find looks for a value in a sequence. When it succeeds, it returns an iterator to the element it found.
This matters because the result of find is not merely a report that the value exists. It is a position you can use to work with that element. The iterator is the handle you then apply to the element.
Tracing a find Call Step by Step
The trace below uses a generic sequence of four elements and a value you are searching for. The steps describe the successful case that the source explains. The source does not describe what find returns when the value is missing, so this trace does not claim anything about that case.
Locating a value and then working with it
A sequence holds the values 4, 9, 2, 7 in that order. You want to find the value 2 and then work with that particular element.
- 1Ask find to search
You give find the sequence and the value 2. find looks for that value in the sequence.
- 2Scan the elements
find checks the elements in the sequence. The value 4 does not match, and neither does 9. The value 2 matches at the third position.
- 3Receive the iterator
Because the search succeeded, find returns an iterator to the element it found, which is the element with value 2.
- 4Use the iterator
You now hold a position that refers to that element. Any work you do through this iterator is work on the element in the sequence itself.
find returned an iterator to the element with value 2, and that iterator is what you use to work with the element next.
Choosing Between the Two Sources
The two sources answer different situations. When you first encounter a container and want to work through its elements, the iterator comes directly from the container. When you call an algorithm such as find to locate a value, the iterator comes back as the algorithm's return value. The table below sets the two sources side by side.
Deciding Which Source Applies
When you face a task, you can predict the source by asking one question: does the task begin with a search for a particular value? If so, the iterator you need is the one an algorithm returns. If the task starts from the container itself, you ask the container for its iterators. The flowchart below turns this into a sequence of decisions.
What do you think happens?
You have a collection and you need to start at its first element. Which source gives you the iterator?
Reveal answer
The container, through begin()
begin() is one of the source's examples of iterators obtained directly from a container. No search for a particular value is involved, so an algorithm's return value is not the source here.
A program has a list of customer names and needs to work with the entry for the name Dana. Which source of iterators applies, and why? Then describe how you would confirm your answer using the flowchart.
Hints
- Ask whether the task starts from a search for a particular value.
- The name Dana is a particular value you are looking for.
Mistakes When Sourcing Iterators
Common mistake Treating the container's contents as a copy you can work on freely
Why it failsThe source says these iterators refer to useful elements, meaning they point into the container. Work done through them is work on the container's own elements.
Do this insteadThink of each iterator as a position inside the container, not as an independent copy of the data.
Common mistake Expecting find to return only a yes or no answer
Why it failsThe source states that find returns an iterator to the element it found, which is a position you can act on, not only a report that the value exists.
Do this insteadWhen find succeeds, use the iterator it returns to work with the found element.
Common mistake Assuming every iterator comes from an algorithm
Why it failsThe section names two sources. An iterator obtained by first encountering a container, such as one from
begin(), does not come from a search.Do this insteadAsk whether the task starts from a search for a particular value before deciding the source.
Key Takeaways
- Iterators come from two sources: directly from a container when you first encounter it, and as the return value of an algorithm.
begin()andend()are the source's examples of iterators obtained from a container.- The standard algorithm find returns an iterator to the element it found when it succeeds, giving you a position to work with rather than only a yes or no answer.
- To predict the source, ask whether the task starts from a search for a particular value: if so, expect an algorithm's return value; if not, ask the container.