74
#include <list>
using std::list;

int main()
{
    list <int> n;
    n.push_back(1);
    n.push_back(2);
    n.push_back(3);

    list <int>::iterator iter = n.begin();
    std::advance(iter, n.size() - 1); //iter is set to last element
}

is there any other way to have an iter to the last element in list?

cpx
  • 17,009
  • 20
  • 87
  • 142

7 Answers7

114

Yes, you can go one back from the end. (Assuming that you know that the list isn't empty.)

std::list<int>::iterator i = n.end();
--i;
CB Bailey
  • 755,051
  • 104
  • 632
  • 656
84

Either of the following will return a std::list<int>::iterator to the last item in the list:

std::list<int>::iterator iter = n.end();
--iter;

std::list<int>::iterator iter = n.end();
std::advance(iter, -1);

// C++11
std::list<int>::iterator iter = std::next(n.end(), -1);

// C++11
std::list<int>::iterator iter = std::prev(n.end());

The following will return a std::list<int>::reverse_iterator to the last item in the list:

std::list<int>::reverse_iterator iter = std::list::rbegin();
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Will `std::list::iterator iter = --n.end();` work as well or the decrement will be done only after the assignment? – mbrandalero May 02 '18 at 11:20
  • 1
    @mbrandalero it should work fine. The result of the decrement will be assigned to the variable – Remy Lebeau May 02 '18 at 14:45
  • @RemyLebeau That might not always work (i.e. for iterators more generally, not just class-type ones), as iterators are not required to be modifiable lvalues. See [Why can't I decrement std::array::end()?](https://stackoverflow.com/questions/48187786/why-cant-i-decrement-stdarrayend) for good discussion. So, basically, wrapping it in `std::prev()` is better style. – underscore_d Sep 22 '18 at 10:31
  • @mbrandalero *If* using predecrement is usable for a given iterator (see above comment), the decrement **must** be done before the assiignment, as that is how the entire world expects prefix operators to work, and any iterator not doing that would be dismally broken. – underscore_d Sep 22 '18 at 10:36
11

With reverse iterators:

iter = (++n.rbegin()).base()

As a side note: this or Charles Bailey method have constant complexity while std::advance(iter, n.size() - 1); has linear complexity with list [since it has bidirectional iterators].

Eugen Constantin Dinca
  • 8,994
  • 2
  • 34
  • 51
  • Why "++n.rbegin()" ? To me that seems like a reverse iterator to the next to last element. Wouldn't "n.rbegin().base()" (without the "++") be the iterator to the last element ? – zentrunix Sep 11 '14 at 12:40
  • @JoséX. base() is not just shorthand for casting an reverse iterator into a forward iterator. Take a look at this response for more info about base: http://stackoverflow.com/a/16609146/153861 – Eugen Constantin Dinca Sep 22 '14 at 09:47
7

Take the end() and go one backwards.

list <int>::iterator iter = n.end();
cout << *(--iter);
cpx
  • 17,009
  • 20
  • 87
  • 142
Mitten.O
  • 575
  • 4
  • 14
6
std::list<int>::iterator iter = --n.end();
cout << *iter;
B Faley
  • 17,120
  • 43
  • 133
  • 223
  • 2
    Prefix operators on rvalue iterators will only work in some cases and are not required to, so you should instead use `std::prev()`; see https://stackoverflow.com/questions/2678175/iterator-to-last-element-in-stdlist#comment91853941_2678214 – underscore_d Sep 22 '18 at 10:41
1

You could write your own functions to obtain a previous (and next) iterator from the given one (which I have used when I've needed "look-behind" and "look-ahead" with a std::list):

template <class Iter>
Iter previous(Iter it)
{
    return --it;
}

And then:

std::list<X>::iterator last = previous(li.end());

BTW, this might also be available in the boost library (next and prior).

Jan Hudec
  • 73,652
  • 13
  • 125
  • 172
UncleBens
  • 40,819
  • 6
  • 57
  • 90
0
list<int>n;
list<int>::reverse_iterator it;
int j;

for(j=1,it=n.rbegin();j<2;j++,it++)
cout<<*it;
  • 3
    Explaining the code you posted would make your answer even better. –  Nov 21 '12 at 00:13