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
?
CodePudding user response:
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.