Just a little introduction, with simple words. In C++, iterators are "things" on which you can write at least the dereference operator *it
, the increment operator ++it
, and for more advanced bidirectional iterators, the decrement --it
, and last but not least, for random access iterators we need operator index it[]
and possibly addition and subtraction.
Such "things" in C++ are objects of types with the according operator overloads, or plain and simple pointers.
std::vector<>
is a container class that wraps a continuous array, so pointer as iterator makes sense. On the nets, and in some literature you can find vector.begin()
used as a pointer.
The rationale for using a pointer is less overhead, higher performance, especially if an optimizing compiler detects iteration and does its thing (vector instructions and stuff). Using iterators might be harder for the compiler to optimize.
Knowing this, my question is why modern STL implementations, let's say MSVC++ 2013 or libstdc++ in Mingw 4.7, use a special class for vector iterators?
An iterator is an object (like a pointer) that points to an element inside the container. We can use iterators to move through the contents of the container.
A pointer hold an address in memory. An iterator may hold a pointer, but it may be something much more complex. For example, an iterator can iterate over data that's on file system, spread across many machines, or generated locally in a programmatic fashion.
After all, iterators are invalidated at mostly the same times and the same ways as pointers, and one reason that iterators exist is to provide a way to "point" at a contained object. So, if you have a choice, prefer to use iterators into containers.
Smart pointer like std::unique_ptr are implemented to store a pointer and behave like a C pointer, while iterators also are pointers themselves.
You're completely correct that vector::iterator
could be implemented by a simple pointer (see here) -- in fact the concept of an iterator is based on that of a pointer to an array element. For other containers, such as map
, list
, or deque
, however, a pointer won't work at all. So why is this not done? Here are three reasons why a class implementation is preferrable over a raw pointer.
Implementing an iterator as separate type allows additional functionality (beyond what is required by the standard), for example (added in edit following Quentins comment) the possibility to add assertions when dereferencing an iterator, for example, in debug mode.
overload resolution If the iterator were a pointer T*
, it could be passed as valid argument to a function taking T*
, while this would not be possible with an iterator type. Thus making std::vector<>::iterator
a pointer in fact changes the behaviour of existing code. Consider, for example,
template<typename It> void foo(It begin, It end); void foo(const double*a, const double*b, size_t n=0); std::vector<double> vec; foo(vec.begin(), vec.end()); // which foo is called?
argument-dependent lookup (ADL; pointed out by juanchopanza) If you make an unqualified call, ADL ensures that functions in namespace std
will be searched only if the arguments are types defined in namespace std
. So,
std::vector<double> vec; sort(vec.begin(), vec.end()); // calls std::sort sort(vec.data(), vec.data()+vec.size()); // fails to compile
std::sort
is not found if vector<>::iterator
were a mere pointer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With