Iterator Categories
rather than
The same applies to decrement operators, as long as they are defined (they aren't for input iterators).
Forward iterators are combinations of input and output iterators. They have all the abilities of input iterators and most of those of output iterators. Table below summarizes the operations of forward iterators.
Bidirectional iterators are forward iterators that provide the additional ability to iterate backward over the elements. Thus, they provide the decrement operator to step backward (table below).
The following program demonstrates the special abilities of random access iterators:
Iterators are objects that can iterate over elements of a sequence. They do
this via a common interface that is adapted from ordinary pointers. Iterators
follow the concept of pure abstraction: Anything that behaves like an
iterator is an iterator. However, iterators have different abilities.
These abilities are important because some algorithms require special iterator
abilities. For example, sorting algorithms require iterators that can perform
random access because otherwise the run-time would be poor. For this reason,
iterators have different categories (figure below). The abilities of these categories are listed in table below, and discussed in the following coming posts.
Figure:- Iterator Categories
Iterator Category | Ability | Providers |
---|---|---|
Input iterator | Reads forward | istream |
Output iterator | Writes forward | ostream, inserter |
Forward iterator | Reads and writes forward | |
Bidirectional iterator | Reads and writes forward and backward | list, set, multiset, map, multimap |
Random access iterator | Reads and writes with random access | vector, deque string, array |
Input Iterators
Input iterators can only step forward element-by-element with read access.
Thus, they return values elementwise. Table below lists the operations of input iterators.
Note that input iterators can read elements only once. Thus, if you copy an
input iterator and let the original and the copy read forward, they might
iterate over different values.
Almost all iterators have the abilities of input iterators. However, usually
they can have more. A typical example of a pure input iterator is an iterator
that reads from the standard input (typically the keyboard). The same value
can't be read twice. After a word is read from an input stream (out of the input
buffer), the next read access returns another word.
Two input iterators are equal if they occupy the same position. However, as
stated previously, this does not mean that they return the same value on element
access.
Expression | Effect |
---|---|
*iter | Provides read access to the actual element |
iter ->member | Provides read access to a member (if any) of the actual element |
++iter | Steps forward (returns new position) |
iter++ | Steps forward (returns old position) |
Iter1 == iter2 | Returns whether two iterators are equal |
Iter1 != iter2 | Returns whether two iterators are not equal |
TYPE(iter) | Copies iterator (copy constructor) |
You should always prefer the preincrement operator over the postincrement
operator because it might perform better. This is because the preincrement
operator does not have to return an old value that must be stored in a temporary
object. So, for any iterator pos (and any abstract data
type), you should prefer
rather than
The same applies to decrement operators, as long as they are defined (they aren't for input iterators).
Output Iterators
Output iterators are the counterparts of input iterators. They can only step
forward with write access. Thus, you can assign new values only
element-by-element. You can't use an output iterator to iterate twice over the
same range. The goal is to write a value into a "black hole" (whatever that
means). So, if you write something for the second time at the same position into
the same black hole, it is not guaranteed that you will overwrite a previous
value. Table below lists the valid
operations for output iterators. The only valid use of operator * is on the left side of an assignment statement.
Expression | Effect |
---|---|
*iter = value | Writes value to where the iterator refers |
++iter | Steps forward (returns new position) |
iter++ | Steps forward (returns old position) |
TYPE (iter) | Copies iterator (copy constructor) |
Note that no comparison operations are required for output iterators. You
can't check whether an output iterator is valid or whether a "writing" was
successful. The only thing you can do is to write, and write, and write
values.
Usually iterators can read and write values. So, as for input iterators,
almost all iterators also have the abilities of output iterators. A typical
example of a pure output iterator is an iterator that writes to the standard
output (for example, to the screen or a printer). If you use two output
iterators to write to the screen, the second word follows the first rather than
overwriting it. Another typical example of output iterators are inserters.
Inserters are iterators that insert values into containers. If you assign a
value, you insert it. If you then write a second value, you don't overwrite the
first value; you just also insert it.
Forward Iterators
Forward iterators are combinations of input and output iterators. They have all the abilities of input iterators and most of those of output iterators. Table below summarizes the operations of forward iterators.
Expression | Effect |
---|---|
*iter | Provides access to the actual element |
iter-> member | Provides access to a member of the actual element |
++iter | Steps forward (returns new position) |
iter++ | Steps forward (returns old position) |
iter1 == iter2 | Returns whether two iterators are equal |
iter1 != iter2 | Returns whether two iterators are not equal |
TYPE() | Creates iterator (default constructor) |
TYPE(iter) | Copies iterator (copy constructor) |
iter1 = iter2 | Assigns an iterator |
Unlike input iterators and output iterators, forward iterators can refer to
the same element in the same collection and process the same element more than
once. You might wonder why a forward iterator does not have all of the abilities of
an output iterator. One restriction applies that prohibits valid code for output
iterators from being valid for forward iterators:
- For output iterators, writing data without checking for the end of a sequence is correct. In fact, you can't compare an output iterator with an end iterator because output iterators do not have to provide a comparison operation. Thus, the following loop is correct for output iterator pos:
- For forward iterators, you must ensure that it is correct to dereference (access the data) before you do this. Thus, the previous loop is not correct for forward iterators. This is because it would result in dereferencing the end() of a collection, which results in undefined behavior. For forward iterators, the loop must be changed in the following manner:
Bidirectional Iterators
Bidirectional iterators are forward iterators that provide the additional ability to iterate backward over the elements. Thus, they provide the decrement operator to step backward (table below).
Expression | Effect |
---|---|
-- iter | Steps backward (returns new position) |
iter-- | Steps backward (returns old position) |
Random Access Iterators
Random access iterators are bidirectional iterators that can perform random
access. Thus, they provide operators for "iterator arithmetic" (in accordance
with the "pointer arithmetic" of ordinary pointers). That is, they can add and
subtract offsets, process differences, and compare iterators with relational
operators such as < and >. Table lists the additional
operations of random access iterators.
Random access iterators are provided by the following objects and types:
-
Containers with random access (vector, deque)
-
Strings (string, wstring)
- Ordinary arrays (pointers)
Expression | Effect |
---|---|
iter[n] | Provides access to the element that has index n |
iter+=n | Steps n elements forward (or backward, if n is negative) |
iter-=n | Steps n elements backward (or forward, if n is negative) |
iter+n | Returns the iterator of the nth next element |
n+iter | Returns the iterator of the nth next element |
iter-n | Returns the iterator of the nth previous element |
iter1-iter2 | Returns the distance between iter1 and iter2 |
iter1<iter2 | Returns whether iter1 is before iter2 |
iter1>iter2 | Returns whether iter1 is after iter2 |
iter1<=iter2 | Returns whether iter1 is not after iter2 |
iter1>=iter2 | Returns whether iter1 is not before iter2 |
The following program demonstrates the special abilities of random access iterators:
-----------------------------------------------------------------
See Also:
-----------------------------------------------------------------
See Also:
-----------------------------------------------------------------
- Complete Tutorial of C++ Template's
- Standard Template Library Tutorial
- Inter Process Communication Tutorial
- Advance Programming in C & C++
-----------------------------------------------------------------
No comments:
Post a Comment