STL Iterator Classes


What is the STL? string vector list sort find

Iterators are special STL objects that represent positions of elements in various STL containers. Simplistically, they play a role similar to that of a subscript in a C++ array, permitting the programmer to access a particular element, and to traverse through the container. There are many different kinds of iterators, depending on the type of container with which they are associated. For the purposes of this discussion, only a few simple iterator capabilities will be considered.

Declaring an iterator

Because an iterator object is always associated with one specific type of container object, its type depends on the type of the container. For example:

#include <list>
#include <vector>
using namespace std;
...
list<int> nums;
list<int>::iterator nums_iter;
vector<double> values;
vector<double>::iterator values_iter; 
vector<double>::const_iterator const_values_iter; 

At any given time, an iterator object is associated with only one container object. There are several basic types of iterators:

Iterator type Capabilities
Forward Can specify the position of a single element in a container.

Can move in one direction from element to element in a container.

Bidirectional Same as forward iterator, but can move in two directions ("forward" and "reverse") from element to element.
Random access Same as bidirectional iterator, but can also move in bigger steps (skipping multiple elements).

Iterators may be const (e.g., "const_iterator") or non-const. Constant iterators can be used to examine container elements, but not modify them. Non-constant iterators may not be used with constant container objects. Further, some specialized STL containers do not permit the use of non-constant iterators.

Iterator operators

Various operators can be applied to an iterator object, depending on its type:

Operator Description Forward Bidirectional Random access
== Returns true if two iterator values specify the same element position, false otherwise. Valid only if both iterator values are associated with the same container object. Check mark Check mark Check mark
!= Returns true if two iterator values do NOT specify the same element position, false if they do. Valid only if both iterator values are associated with the same container object. Check mark Check mark Check mark
* Returns a reference to the container element at the position specified by the iterator. Valid only if there is an element at that position.

The reference can be used to examine or modify the element. For constant container objects (and for some specialized STL containers, constant or not), the reference is constant; in this case, it can only be used to examine the container element, not modify it.

See the note below on invoking member functions of an object referenced by an iterator.
Check mark Check mark Check mark
++ Increments the iterator's value, so it specifies the next position in the associated container. Check mark Check mark Check mark
-- Decrements the iterator's value, so it specifies the previous position in the associated container.   Check mark Check mark
+=
-=
+
-
Adds or subtracts an offset from the iterator's value, moving it forward or backward by a specified number of positions within the container.     Check mark
<
>
<=
>=
Compares two iterator values and returns true or false, depending on whether the specified relationship is true. Valid only if both iterator values are associated with the same container.     Check mark

Iterator usage

Iterators have many uses. A few examples are included here.

List element access

After creating a list of integers and adding some elements, we initialize the iterator nums_iter to specify the first list position (nums.begin()). The loop runs until we reach the iterator value that represents the position "just beyond" the last list element (nums.end()). Each list element is accessed by the "*" operator, which returns a reference to the element. The increment operator (++) moves the iterator to the next position in the list.

Note that we are using the iterator to modify the list elements. If this were not the case, the iterator could have been declared as "list<int>::const_iterator nums_iter;".

#include <list>		// list class library
using namespace std;
...
  list<int> nums;
  list<int>::iterator nums_iter;
  nums.push_back (0);
  nums.push_back (4);
  nums.push_front (7);

  cout << endl << "List 'nums' now becomes:" << endl;
  for (nums_iter=nums.begin(); nums_iter != nums.end(); nums_iter++)
  {
    *nums_iter = *nums_iter + 3; // Modify each element.
    cout << (*nums_iter) << endl;
  }
  cout << endl; 

Invoking member functions of an object referenced by an iterator

Very often, the elements stored in an STL container are objects of class type. In this case, we may want to invoke member functions of the object referenced by an iterator. To do so, we have to watch out for operator precedence, so that the compiler understands what we are trying to do. For example:

#include <list>  	// list class library
#include <string> // string class library
using namespace std;
...
  list<string> words;
  list<string>::iterator words_iter;
...
  unsigned int total_length = 0;
  for (words_iter=words.begin(); words_iter != words.end(); words_iter++)
  {
    total_length += (*words_iter).length();  // correct
//  total_length += *words_iter.length();    // incorrect !!
  }
  cout << "Total length is " << total_length << endl; 

 The parentheses around "*words_iter" are required when we invoke the "length()" member function. Without them, the compiler would think that the "length()" function is a member of the iterator class, not of the string class, since the "." operator would otherwise be evaluated before the unary "*" operator.

As you might expect, the parentheses would also be required if we wish to access a data member of an object referenced by an iterator.

Using iterators with container member functions and STL algorithms

Some STL functions (both container member functions and algorithms) require iterator arguments. This following example illustrates iterator usage by:

#include <vector>       // vector class library
#include <list>		// list class library
#include <algorithm>		// STL algorithms class library
using namespace std;
...
  vector<string> vec1;

  string state1 = "Wisconsin";
  string state2 = "Minnesota";
  vec1.push_back (state1);
  vec1.push_back (state2);
  vec1.push_back ("Illinois");
  vec1.push_back ("Michigan");
  sort(vec1.begin(),vec1.end()); // Sort the vector of strings.

  vec1.erase(vec1.begin(),vec1.end());
...
  list<int> nums;
  list<int>::iterator nums_iter;
...
  nums.erase (nums.begin(), nums.end()); // Remove all elements.
...
  nums_iter = find(nums.begin(), nums.end(), 3); // Search the list.
  if (nums_iter != nums.end())
  {
    cout << "Number " << (*nums_iter) << " found." << endl;
  }
...
  // If we found the element, erase it from the list.
  if (nums_iter != nums.end()) nums.erase(nums_iter); 


This document was written by Dr. Mark J. Sebern (See stl) and last updated on December 13, 1998