There's a fourth option (not necessarily a good option, but it exists). You can use bidirectional/random access iterators in a fashion that mimics how reverse iterators are implemented to avoid the problem with myvec.end()-1
on an empty iterator:
for (vector<int>::iterator it = myvec.end(); it != myvec.begin(); --it)
{
// convert the loop controlling iterator to something that points
// to the item we're really referring to
vector<int>::iterator true_it = it;
--true_it;
// do stuff here
// but always dereference `true_it` instead of `it`
// this is essentially similar to the way a reverse_iterator
// generally works
int& x = *true_it;
}
or even:
for (vector<int>::iterator it = myvec.end(); it != myvec.begin();)
{
// decrement `it` before the loop executes rather than after
// it's a bit non-idiomatic, but works
--it;
int& x = *it;
// do stuff...
}
Like I said, this is not necessarily a good option (I think Jerry Coffin's answer is the approach you should look to first), but I think it's of interest since it shows how reverse iterators work behind the scenes - and it avoids having to convert a reverse_iterator to a iterator for those times when you might want to use the iterator with something that won't accept a reverse_iterator
(converting reverse_iterator
s to iterator
s always seems to make my head hurt, so I'll often avoid reverse_iterators
to avoid headaches). For example, if you want to call insert() for the location a reverse iterator is referring to:
// if `it` is a reverse iterator, a call to insert might have to look something like:
myvec.insert( --(it.base()), 42 ); // assume that you know the current vector capacity
// will avoid a reallocation, so the loop's
// iterators won't be invalidated
// if `it` is a normal iterator...
myvec.insert( it, 42 );