views:

149

answers:

4

Is it possible to iterate a vector from the end to the begin?

for (vector<my_class>::iterator i = my_vector.end();
        i != my_vector.begin(); /* ?! */ ) {
}

Or is that only possible with something like that:

for (int i = my_vector.size() - 1; i >= 0; --i) {
}
+5  A: 

User rend() / rbegin() iterators:

for (vector<myclass>::reverse_iterator it = myvector.rbegin(); it != myvector.rend(); it++)

a1ex07
+1  A: 

Use reverse iterators and loop from rbegin() to rend()

Steve Townsend
+13  A: 

Well, the best way is:

for (vector<my_class>::reverse_iterator i = my_vector.rbegin(); 
        i != my_vector.rend(); ++i ) { 
} 

rbegin()/rend() especically designed for that purpose. (And yes, incrementing a reverse_interator moves it backward)

Now, in theory, your method (using begin/end & --i) would work, vector's iterator being bidirectional, But remember, end() isn't the last element -- it's one beyond the last element, so you'd have to decrement first, and you are done when you reach begin() -- but you still have to do your processing.

vector<my_class>::iterator i = my_vector.end();
while (i != my_vector.begin())
{
     --i;
    /*do stuff */ ) 

} 

UPDATE: I was apparently too aggressive in re-writing the for() loop into a while loop. (The important part is the the --i is at the beginning.)

James Curran
Shouldn't it be `reverse_iterator` ?
a1ex07
@a1ex07: right, thanks!
James Curran
I just realized that `--i` will cause a big problem if container is empty... Before going into `do - while` loop it makes sense to check `(my_vector.begin() != my_vector.end())`.
a1ex07
Why are you using a `do-while` loop instead of just a `while` loop? Then you wouldn't need any special check for empty vectors.
jamesdlin
A: 

The well-established "pattern" for reverse-iterating through closed-open ranges looks as follows

// Iterate over [begin, end) range in reverse
for (iterator = end; iterator-- != begin; ) {
  // Process `*iterator`
}

or, if you prefer,

// Iterate over [begin, end) range in reverse
for (iterator = end; iterator != begin; ) {
  --iterator;
  // Process `*iterator`
}

This pattern is usable, for example, for reverse-indexing an array using an unsigned index

int array[N];
...
// Iterate over [0, N) range in reverse
for (unsigned i = N; i-- != 0; ) {
  array[i]; // <- process it
}

(People unfamiliar with this pattern often insist on using signed integer types for array indexing specifically because they incorrectly believe that unsigned types prevent reverse indexing)

It can be used for iterating over an array using a "sliding pointer" technique

// Iterate over [array, array + N) range in reverse
for (int *p = array + N; p-- != array; ) {
  *p; // <- process it
}

or it can be used for reverse-iteration over a vector using an ordinary (not reverse) iterator

for (vector<my_class>::iterator i = my_vector.end(); i-- != my_vector.begin(); ) {
  *i; // <- process it
}
AndreyT