(Remember, this is all very simplified.)
template vector { private: T* elements; int length, capacity; public: vector() : length(0), capacity(INIT) { elements = new T[INIT]; } typedef T* iterator; iterator begin() { return &elements[0]; } iterator end() { return &elements[length]; } }; Here we see that by requiring that iterators conform to the syntax of pointers, we can actually implement an iterator directly as a pointer. For a linked list iterator, we would have to define a class that overloaded the *, ++, and possibly == and != operators.
In any case, you do not have to understand the internals of how iterators work to use them. You only need to understand the usage of begin(), end(), ++, and *.
Containers allow us to store elements of arbitrary type. Iterators generalize the idea of traversing the elements in a container in order. Given these pieces, we can define a set of generalized algorithm templates that use iterators to manipulate collections of objects.
Another way of looking at the relationship among these three parts is to say that iterators form the bridge between generic containers and generic algorithms: