Auxiliary Iterator Functions
The C++ standard library provides three auxiliary
functions for iterators: advance(), distance(), and iter_swap(). The first two give all iterators some abilities
usually only provided for random access iterators: to step more than one element
forward (or backward) and to process the difference between iterators. The third
auxiliary function allows you to swap the values of two iterators.
Stepping Iterators Using advance()
The function advance() increments the position of an
iterator passed as the argument. Thus, it lets the iterator step forward (or
backward) more than one element:
-
Lets the input iterator pos step n elements forward (or backward).
-
For bidirectional and random access iterators n may be negative to step backward.
-
Dist is a template type. Normally, it must be an integral type because operations such as <, ++, --, and comparisons with 0 are called.
-
Note that advance() does not check whether it crosses the end() of a sequence (it can't check because iterators in general do not know the containers on which they operate). Thus, calling this function might result in undefined behavior because calling operator ++ for the end of a sequence is not defined.
Due to the use of iterator traits, the function always uses the
best implementation, depending on the iterator category. For random access
iterators, it simply calls pos+=n. Thus, for such iterators advance() has constant complexity. For all other iterators,
it calls ++pos n times (or --pos, if n is negative). Thus,
for all other iterator categories advance() has linear
complexity.
To be able to change container and iterator types, you should use advance() rather than operator +=.
However, in doing so be aware that you risk unintended worse performance. This
is because you don't recognize that the performance is worsening when you use
other containers that don't provide random access iterators (bad runtime is the
reason why operator += is provided only for random
access iterators). Note also that advance() does not
return anything. Operator += returns the new position,
so it might be part of a larger expression. Here is an example of the use of advance():
In this program, advance() lets the iterator pos step three elements forward and one element backward.
Thus, the output is as follows:
Another way to use advance() is to ignore some input
for iterators that read from an input stream.
Processing Iterator Distance Using distance()
The distance() function is provided to process the
difference between two iterators:
-
Returns the distance between the input iterators pos1 and pos2.
-
Both iterators have to refer to elements of the same container.
-
If the iterators are not random access iterators, pos2 must be reachable from pos1; that is, it must have the same position or a later position.
-
The return type, Dist, is the difference type according to the iterator type:
By using iterator tags, this function uses the best implementation according
to the iterator category. For random access iterators, it simply returns
pos2-pos1. Thus, for such iterators distance()
has constant complexity. For all other iterator categories, pos1 is
incremented until it reaches pos2 and the number of incrementations is
returned. Thus, for all other iterator categories distance() has linear complexity. Therefore, distance() has bad performance for other than random access
iterators. You should consider avoiding it.
The following example
demonstrates its use:
find() assigns the position of the element with value 5 to pos. distance() uses this position to process the difference between this position and the beginning. The output of the program is as follows:
To be able to change iterator and container types, you should use distance() instead of operator-.
However, if you use distance() you don't recognize that
the performance is getting worse when you switch from random access iterators to
other iterators.
To process the difference between two iterators that are not random access
iterators, you must be careful. The first iterator must refer to an element that
is not after the element of the second iterator. Otherwise, the behavior is
undefined. If you don't know which iterator position comes first, you have to
process the distance between both iterators to the beginning of the container
and process the difference of these distances. However, you must then know to
which container the iterators refer. If you don't, you have no chance of
processing the difference of the two iterators without running into undefined
behavior.
In older versions of the STL, the signature of distance() was different. Instead of the difference being
returned, it was added to a third argument. This version was very inconvenient
because you could not use the difference directly in an expression. If you are
using an old version, you should define this simple workaround:
Here, the return type does not depend on the iterator; it is hard coded as long. Type long normally should be big enough to fit all possible values, however this is not guaranteed.
Swapping Iterator Values Using iter_swap()
The following simple auxiliary function is provided to swap the values to
which two iterators refer:
-
Swaps the values to which iterators pos1 and pos2 refer.
-
The iterators don't need to have the same type. However, the values must be assignable.
Here is a simple example
The output of the program is as follows:
Note that this program normally does not work if you use a vector as a
container. This is because ++coll.begin() and --coll.end() yield temporary pointers.
-----------------------------------------------------------------
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