Why doesn't using `std :: reverse_iterator` call UB?

I worked with today std::reverse_iterator

and was thinking about how it works with values โ€‹โ€‹created when called begin

in a container. According to cppreference , if I have reverse_iterator r

one built from iterator i

, the next value should contain &*r == &*(i-1)

.

However, this would mean that if I write this

std::vector<int> vec = {1, 2, 3, 4, 5};
auto iter = std::make_reverse_iterator(begin(vec));

      

iter now points to a piece of memory that is placed before begin(vec)

, which is out of scope. By strict interpretation of the C ++ standard, this calls UB.

(There is a specific position for pointer / iterator for item 1-past-the-end of the array, but as far as I know, none for pointer / iterator to item 1-ahead of the start of the array.)

So, am I reading the link incorrectly, or is there a specific provision in the standard for this case, or is it, when used reverse_iterator

, the entire array is assumed to be inverse and as such, is the pointer ahead of the array actually pointing to the end?

+3


source to share


2 answers


Yes, you are reading this wrong.

There is no need for repeated iterators to store pointers pointing before the start of the element.

To illustrate, take an array of two elements:

int a[2];

      

These are forward iterators:



a+0 a+1 a+2 // The last one is not dereferenceable

      

Reverse iterators will be presented with these exactly the same values โ€‹โ€‹in reverse order:

a+2 a+1 a+0 // The last one cannot be dereferenced

      

So, when dereferencing a normal iterator is really simple, dereferencing with a reverse iterator is a little more complicated: pointer[-1]

(for random access iterators, the others are worse :) It copy = pointer; --copy; return *copy;

.

Keep in mind that the use of forward iterators is much more common than reverse iterators, so the former have more optimistic code for them than the latter. Generic code that does not fall into this corner is likely to work better with any type, because of all the conversions a decent optimizing compiler does.

+5


source


std::make_reverse_iterator(begin(vec))

is not dereferenced, in the same way that end(vec)

it is not dereferenced. It doesn't "point" to any valid object, and that's OK.



+4


source







All Articles