Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Arithmetic on end() iterator

Tags:

c++

iterator

stl

Let A be a std::vector<double>,

Is this well-defined?

if(!A.empty())
    std::vector<double>::iterator myBack = A.end() - 1;

Is the end iterator only good for equalities and inequalities checks? Or I can perform some pointer arithmetic as long as I remain in the container?

On my platform this code works. I'm wondering if this is portable.

like image 421
jimifiki Avatar asked Sep 19 '14 07:09

jimifiki


2 Answers

It is perfectly valid as vector::iterator is a random access iterator. You can perform arithmetic operations on it and it is not platform dependent.

std::vector<double>::iterator it = A.end();
while (it != A.begin()){
    --it; //this will skip A.end() and loop will break after processing A.front()
    //do something with 'it'
}

But A.end() refers to theoretical past-the-end element, so it does not point to an element and thus shall not be dereferenced. So best practice is to use reverse iterator instead of decrementing end iterator.

for(std::vector<double>::reverse_iterator it = A.rbegin(); it != A.rend(); ++it) {
    //do something with 'it'
}

These two loops do the same thing, second is just understandable, cleaner way to do it.

like image 103
Cem Özer Avatar answered Sep 28 '22 03:09

Cem Özer


It's almost safe if you are mindful of some exceptional cases:

A.end() gives you an iterator denoting the position just beyond the end of the std::vector. You should not attempt to dereference it.

If the vector has zero elements then A.end() - 1 is not well-defined. In all other cases it is and you can indeed perform pointer arithmetic so long as you are in the container bounds. Note that the standard guarantees that the std::vector data are contiguous and packed in exactly the same way as an C++ array of the contains type. The only exception is std::vector<bool> which behaves differently due to a standards-specified tight packing specialisation. (Note well thatsizeof(bool) is not guaranteed to have a particular value by the standard).

If I were you I'd use A.rbegin() to access the rightmost element and check the return value before proceeding and stick to the iterator formulation. It's all too easy to forget the std::vector<bool> specialisation.

like image 40
Bathsheba Avatar answered Sep 28 '22 02:09

Bathsheba