iterator c++
An
iterator is an object that can "iterate" (navigate) over elements.
These elements may be all or part
of the elements of a STL container. An iterator represents a certain position
in a container. The
following fundamental operations define the behavior of an iterator:
- Operator
* : Returns
the element of the actual position. If the elements have members, you can use operator
-> to access those members directly from the
iterator. ( In some older environments, operator -> might
not work yet for iterators.)
- Operator
++ : Lets
the iterator step forward to the next element. Most iterators also allow
stepping backward
by using operator --.
- Operators
== and != : Return
whether two iterators represent the same position.
- Operator
= : Assigns
an iterator (the position of the element to which it refers).
These
operations are exactly the interface of ordinary pointers in C and C++ when
they are used to
iterate over the elements of an array. The difference is that iterators may be smart pointers — pointers
that iterate over more complicated data structures of containers. The internal
behavior of iterators
depends on the data structure over which they iterate. Hence, each container type supplies
its own kind of iterator. In fact, each container class defines its iterator
type as a nested class.
As a result, iterators share the same interface but have different types. This leads directly to
the concept of generic programming: Operations use the same interface but
different types, so you
can use templates to formulate generic operations that work with arbitrary
types that satisfy the
interface.
All
container classes provide the same basic member functions that enable them to
use iterators to
navigate over their elements. The most important of these functions are as
follows:
- begin() : Returns
an iterator that represents the beginning of the elements in the container. The beginning
is the position of the first element (if any).
- end() : Returns
an iterator that represents the end of the elements in the container. The end is the position behind the last
element.
Such an iterator is also called a past-the-end iterator.
Thus,
begin() and end()
define a
half-open range that includes the
first element but excludes the
last (Figure 5.3). A half-open range has two advantages:
Figure. begin() and end() for Containers
- You have a simple end criterion for loops that iterate over the elements: They
simply continue
as long as end() is not reached.
- It avoids special handling for empty ranges. For empty ranges, begin() is
equal to end().
Here
is an example demonstrating the use of iterators. It prints all elements of a
list container (it is the
promised enhanced version of the first list example).
Example:
After
the list is created and filled with the characters 'a' through
'z', all elements are printed within
a for loop:
list<char>::const_iterator pos;
for (pos = coll.begin(); pos !=
coll.end(); ++pos) {
cout << *pos << ' ';
}
The
iterator pos is declared just before the loop. Its type is the iterator type for constant element access
of its container class:
list<char>::const_iterator pos;
Every
container defines two iterator types:
- container::iterator - is
provided to iterate over elements in read/write mode.
- container: : const_iterator - is
provided to iterate over elements in read-only mode.
For
example, in class list the definitions might look like the following:
namespace std {
template <class T>
class list {
public:
typedef ... iterator;
typedef ... const_iterator;
...
};
}
The
exact type of iterator and const_iterator
is
implementation defined.
Inside
the for loop, the iterator pos first
gets initialized with he position of the first element:
pos = coll.begin()
The
loop continues as long as pos has not reached the
end of the container elements:
pos != coll.end()
Here,
pos is compared with the past-the-end iterator.
While the loop runs the increment operator, ++pos navigates the iterator pos to
the next element.
All
in all, pos iterates from the first element,
element- by-element, until it reaches the end (Figure below). If the container has no elements, the loop
does not run because coll.begin() would equal
coll.end().
Figure . Iterator pos Iterating Over
Elements of a List
In
the body of the loop, the expression *pos represents the actual
element. In this example, it is written
followed by a space character. You can't modify the elements because a const_iterator is used. Thus, from
the iterator's point of view the elements are constant.
However,
if you use a nonconstant iterator and the type of the elements is nonconstant,
you can change
the values. For example:
//make all characters in the list
uppercase
list<char>::iterator pos;
for (pos = coll.begin(); pos !=
coll.end(); ++pos) {
*pos = toupper(*pos);
}
Note
that the preincrement operator (prefix ++) is used here. This is because it
might have better performance
than the postincrement operator. The latter involves a temporary object because
it must
return the old position of the iterator. For this eason, it generally is best
to prefer ++pos over
pos++. Thus, you should avoid the following version:
for (pos = coll.begin(); pos !=
coll.end(); pos++) {
^^^^^ //
OK, but slower
...
}
For
this reason, I recommend using the preincrement and pre-decrement operators in
general.
See Also: