51

Code with iterators looks pretty much like code with pointers. Iterators are of some obscure type (like std::vector<int>::iterator for example).

What I don't get is how iterators and pointer are related to each other - is an iterator a wrapper around a pointer with overloaded operations to advance to adjacent elements or is it something else?

David M
  • 71,481
  • 13
  • 158
  • 186
sharptooth
  • 167,383
  • 100
  • 513
  • 979

5 Answers5

65

Iterators are a generalization of pointers.

An iterator (depending on the variants) have to implement * and ++

So a pointer IS an iterator. But not necessarily the other way round.

If you want to iterate over a complex structure (a tree, a graph...), the iterator will be much more than a pointer, and doesn't make any reference to some actual place in the ram.

Tristram Gräbener
  • 9,601
  • 3
  • 34
  • 50
  • 4
    Isn't there a contradiction in this answer? If an iterator is more than a pointer, then surely a pointer cannot be an iterator? – dekuShrub Apr 19 '18 at 07:15
  • Could you please elaborate on what did you mean by "... and doesn't make any reference to some actual place in the ram"? Thank you so much in advance! – Milan Nov 29 '20 at 04:34
  • 3
    For instance, an iterator on the nodes of the graph can be depth or breadth first. So that iterator needs to know where it stands in the graph to retrieve the node. So the iterator is a structure, with attributes and everything. It is more than a memory adress – Tristram Gräbener Dec 01 '20 at 13:14
  • The term RAM IMHO refers to physical memory. A pointer might point to memory that has been swapped to disk. – Thomas Weller Nov 04 '21 at 12:33
  • @dekuShrub "an iterator" is a shorthand for "an instance of a type that models the *iterator* concept". All pointer-to-object types model the *iterator* concept, but there are also some class types that model that concept, e.g. `std::map::iterator` – Caleth May 16 '22 at 15:53
  • 4
    @dekuShrub, _If an iterator is more than a pointer, then surely a pointer cannot be an iterator_. An iterator **is not** (necessarily) more than a pointer, it **can be** more than a pointer. The original phrase was _**if** you want to ..., **[then]** the iterator will be much more than a pointer_. So it is more than pointer in some specific cases. There are different iterators. Some of them (for example, iterators of `std::vector`) are almost pointers, Some of them (for example, iterators of `std::map`) are more complex. A pointer is just the simplest example of iterator. – anton_rh May 16 '22 at 16:03
  • just a simple note , the manual considers a pointer a form of iterator, quoting from here : https://cplusplus.com/reference/iterator/ < The most obvious form of iterator is a pointer...>, end quote, even thought it starts with the following statement again quoting from the reference < An iterator is any object that .... > end quote, a pointer isn't an object it's a data type. – interesting Sep 23 '22 at 14:50
13

Iterators are objects that overload certain operators, so the usage would look like they were pointers. That's within the capabilities of a given iterator category. Random access iterators look entirely like pointers, other types of iterators don't provide some operations (e.g list<X>::iterator which is bidirectional doesn't have operator += among many others that would require random access).

As to the "obscure names", it is not completely unthinkable to use a plain pointer for an iterator:

 template <class T>
 class MyContainer
 {
     ...
     typedef T* iterator;
 }

 MyContainer<int>::iterator it; //the type is really int*
UncleBens
  • 40,819
  • 6
  • 57
  • 90
9

Conceptually, yes -- but they need not be pointers. Their internals and capabilities will depend on the data structure they "wrap".

That is why there are different "classes" of iterators. E.g. Unidirectional, Bidirectional, RandomAccess, etc.

Some are capable of multiple classes.

E.g. if the internal structure is a Red-Black tree or Linked List, the iterators might be Bidirectional, but not RandomAccess. If they wrap a vector (implemented as an array), you'll have RandomAccess and Bidirectional.

Alex Budovski
  • 17,947
  • 6
  • 53
  • 58
6

An iterator is just a type that provides the interface required for iterators - these are different for the different types of iterators and are specified in section 24.1 of the C++ standard (Iterator Requirements).

How iterators are implemented is dependent on what they iterate over - for vectors they are commonly a wrapper around a single pointer to an array (in release builds anyway), for more complex containers they have a more complicated implementation. For open ended ranges they will contain the state of whatever algorithm is beimng used to generate the elements.

Note that a pointer to an element in an array meets the requirements of a random access iterator, so to some extent they are interchangeable.

JoeG
  • 12,994
  • 1
  • 38
  • 63
0

As it was said: iterators are a generalization of pointers. Every pointer is an iterator but not every iterator is a pointer (although most of non-pointer iterators contain pointers within).

Iterator is kind of interface (or concept). We could define the minimum iterator interface as follows:

template <typename T>
class iterator
{
    // Advance to the next element of the collection.
    virtual void operator++() = 0;

    // Get access to the element associated with the iterator.
    virtual const T &operator*() = 0;
};

But there is no real abstract base class for iterators. All functions that take iterators as parameters are template functions, and types for iterator parameters are defined using templates. This is called static polymorphism. We can use std::vector constructor as an example:

template< class InputIt >
vector::vector( InputIt first, InputIt last );

Since InputIt is a type defined using template and since all pointers support operator++() and operator*(), all pointers can be used as iterators. For example:

int arr[3] = {1, 2, 3};
int *begin = &arr[0];
int *end   = &arr[3];

// Initialize vector from a pair of iterators.
std::vector<int> v(begin, end); // The vector `v` will copy to itself
                               // all elements of `arr` in the range from
                              // arr[0] (including) to arr[3] (excluding).

or

std::string str = "hello";
std::string *begin = &str;
std::string *end   = begin + 1;

// Initialize vector from a pair of iterators.
std::vector<std::string> v(begin, end); // The vector `v` will contain
                                       // a single element which is
                                      // string "hello".

Since iterator is just an abstract interface, pointers are not the only example of iterators. Any class that overrides operator++() and operator*() can be used as an iterator. And usually containers use custom classes as iterators instead of pointers. But some functions still use pointers as iterators. An example is std::begin and std::end functions for static arrays:

template< class T, std::size_t N >
T* begin( T (&array)[N] );

template< class T, std::size_t N >
T* end( T (&array)[N] );

There are different types of iterators. The most advanced type of iterator is Random Access Iterator. Besides operator++() and operator*() it supports many other operations like advancing backward (operator--()) or advancing many elements forward at single step (operator+=(size_t n)). Pointers are Random Access Iterators.

This is how pointers and iterators are related.

Resume. Iterators are class of objects that allows to iterate through some collection of elements. Pointers are just an example of iterators but there are others.

anton_rh
  • 8,226
  • 7
  • 45
  • 73