2016-07-18 3 views
3

Мне нужны псевдонимы последних двух элементов в std::list. Последнее легко (.back()), но как я должен получить его перед этим?Получить ссылки на последние два элемента в std :: list

Моя первая идея: получить итератор после последнего элемента (.end()) и переместить его дважды влево. И вот что я «производство»:

&last_but_one = *----myList.end(), 

Хотя это работает, я лично считаю, это какое-то непонятное, и я не думаю, что я бы разобрать его легко, если бы я увидел его в чужом коде ,

Чтение через this answer показывает некоторые другие (слишком) многословным подходы :

auto iter = n.end(); 
std::advance(iter, -2); 
&last_but_one = *iter; // this is overkill! 

// weird, and the .next() variant even more 
&last_but_one = *std::prev(std::prev(n.end())); 

&last_but_one = *++myList.rbegin(); // similar to *----myList.end() 

Какой Предпочитаемый способ сделать это?

Я могу оставить комментарий, но код не требует пояснений.
и, вероятно, медленнее и более сложным, что не должно быть основной причиной для выбора

ответ

10

std::prev() принимает два аргумента. Вы можете использовать вторую один:

auto& second_to_last = *std::prev(list.end(), 2); 

Это именно то, что ваша версия с advance(iter, -2) делает, за исключением того, что возвращает полученный итератор вместо того, чтобы быть void так что вы можете сделать все, что нужно на одной линии.

+0

Ну, это то, о чем я не думал, должен был проверить документы. Выглядит неплохо. И отлично подходит для моей ситуации. Благодаря! –

+0

Кстати, из раздела [примечаний] (http://en.cppreference.com/w/cpp/iterator/prev#Notes): «хотя выражение --c.end() часто компилируется, это не гарантировано сделать это ... »вы можете добавить это к своему ответу. –

+0

@ Al.G. Для 'std :: list <>' вы не получите итератор, который является указателем. – Barry

Смежные вопросы