Section 3 - Iterators

2B.3.1 Iterators

We will see that besides vectors, there are other containers in the STL, notably lists. Another advantage of using STL vectors and lists is that there is a common technique for running through them, a technique whose syntax is identical in both cases. This involves the use of something called iterators.

Iterators are defined alongside vectors (or other containers in STL) . They belong to whatever container class they will access, so in the case of a vector, we will have to use a vector-flavored iterator. We define it simply, like so:

   vector<double>::iterator iter;

(The :: notation reflects the reality that the iterator is nested within the vector class template.) This creates an iterator object, iter, which can be used on a vector of doubles. Iterators make use of the begin() and end() instance methods of the vector class, because those methods return iterators.

Iterators are like pointers - in fact they normally are implemented as actual pointers to their parent class data. An iterator will point to a single element in the vector. They must be dereferenced as pointers, using the * notation, and they make use of the overloaded increment operator, ++, to move them to the next item in the vector. These statements are true of pre-defined iterators in the STL containers classes, and they should be respected when you implement your own template classes and define imbedded iterators. In other words, you should make sure that your iterators return the address of the underlying data, and also overload ++ for the iterator.

Here is a version of our recent program that uses iterators.

#include <iostream>
#include <vector>

using namespace std;

int main()
{
   vector<double> myDoubles;
   vector<double>::iterator iter;

   for ( int k = 0; k < 100 ; k++ )
      myDoubles.push_back(-.01 * k);
   myDoubles.push_back(55.99);
 
   for( iter = myDoubles.begin(); iter != myDoubles.end(); iter++)
      cout << *iter << " ";
   cout << endl;

   return 0;
}

Run:

console shot

2B.3.2 Iterator Details

In reality, the iterator for each container is defined to be a nested class within the container template class. If you define one class, Inner, within another class, Outer, then you can instantiate an Inner object from the client using:

   Outer::Inner innerObject;

This is something we don't usually do. Still, that's what's happening here. If you define a vector of Cards, then you will have a class called vector<Card>. In order to get an iterator for that class, you must instantiate an object of the nested class vector<Card>::iterator. That's where the funny notation comes from. It's not necessary that you understand this level of detail, but C++ programmers do know and use this information, regularly.