In the accepted answer to "Iterator to last element of std::vector using end()--" @barry states:
Note that if vector::iterator is just T* (which would be valid), the first form above is ill-formed. The second two work regardless, so are preferable.
referring to his code:
std::vector<int>::iterator it = --container.end();
std::vector<int>::iterator it = container.end() - 1;
std::vector<int>::iterator it = std::prev(container.end());
This opinion is disputed in the comments, however without a clear resolution. So that's my question: what exactly is the semantic difference between the first and the second? And would the answer be different for iterators over structures other than vector
?
std::vector<T>::iterator satisfies the RandomAccessIterator concept, which means that it has an operator- that allows you to subtract two iterators and obtain a std::vector<T>::iterator::difference_type that indicates the distance between the two iterators.
3. Dereferencing: An input iterator can be dereferenced, using the operator * and -> as an rvalue to obtain the value stored at the position being pointed to by the iterator. 4. Incrementable: An input iterator can be incremented, so that it refers to the next element in the sequence, using operator ++().
The random access iterator can be decremented either by using the decrement operator(- -) or by using arithmetic operation. If itr is an iterator. We can use itr – – or – – itr for decrementing it. As it is a random access iterator we can also use arithmetic operation such as itr=itr-1 for decrementing it.
It appears that you can still decrement the iterator returned from end() and dereference the decremented iterator, as long as it's not a temporary.
For any standard library container, the member function end()
returns an r-value. It's a "temporary" until you assign it to a variable.
The decrement operator --
is not required to work on r-value iterators. You would be modifying a temporary, which C++ historically has taken measures to avoid.
Therefore, --container.end()
might compile on your standard-conforming C++compiler. But it might not.
std::prev(container.end())
will work on every standard-conforming compiler.
To review:
--container.end()
may not compile. It is up to the implementation.container.end() - 1
will only compile if the container uses random-access iterators.std::prev(container.end())
will always compile.All three forms will produce the same result, if they compile.
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