How do I get an iterator to the next-to-last element in a STL list without creating a temporary and modifying the list?
Is it possible to just say: --(--mylist.end())
? Or would this change the end
iterator of the list due to the prefix decrement?
Asked
Active
Viewed 1,470 times
0

ritter
- 7,447
- 7
- 51
- 84
-
1You might want to look at this: http://stackoverflow.com/questions/5322104/how-portable-is-end-iterator-decrement – filmor Jul 12 '12 at 10:16
3 Answers
3
Please note that in general, --mylist.end()
is not guaranteed to compile for every container.
For example, if you use a std::vector
or std::array
in release mode, mylist.end()
is probably a raw pointer, and you cannot decrement a pointer returned by value from a function.
A generic solution to this problem in C++11 is std::prev(std::prev(mylist.end()))
, after checking that the list is long enough, of course. You need to #include <iterator>
for this.

fredoverflow
- 256,549
- 94
- 388
- 662
-
Interesting. But why can't i decrement a pointer returned by value. That's exactly why it doesn't change the `end` iterator itself, due to returning by value – ritter Jul 12 '12 at 10:27
-
Because a call to a function that returns by value is an rvalue, but the `--` operator for scalars (such as ints or raw pointers) requires an lvalue. Just try `--new T();` and you will get a compiler error saying "lvalue required as decrement operand" or something like that. On the other hand, it is perfectly fine to call operator `--` on a temporary object, as long as it is implemented as a member function. In practice, it won't work for *postfix* `--`, because that one is usually implemented as a free function (in terms of prefix `--`, to avoid code duplication), not as a member function. – fredoverflow Jul 12 '12 at 10:32
-
Can you replace "std::prev(std::prev(mylist.end()))" with just "end()-2" for containers with bidirectional iterators like vector ? – Razzle Aug 13 '21 at 16:07
3
You could use std::advance and a reverse_iterator:
SomeContainerType::reverse_iterator it = myList.rbegin();
std::advance(it, 1); // next to last element
This works even if the iterator type in question does not support operator+
.

juanchopanza
- 223,364
- 34
- 402
- 480
-
1Or for that matter a forward iterator: `auto it = myList.end(); std::advance(it, -2);`. – Steve Jessop Jul 12 '12 at 10:53
2
if okay with a reverse_iterator
, then: some_list.rbegin() + 1;

Nim
- 33,299
- 2
- 62
- 101
-
1Assuming `some_list` is a `std::list` the iterator will not support `operator+` – pmr Jul 12 '12 at 10:28
-
1std::list supports bidirectional iterators; as Nim says, just call method rbegin() and take the following elements with operator++ – Bentoy13 Jul 12 '12 at 10:42