Является ли единственным способом получить последний элемент для уменьшения итератора перед разыменованием его?
Нет, есть и другие варианты.
Самый простой способиспользуя обратные итераторы (оба std::set::rbegin
или std::set::crbegin
), которые непосредственно дают вам элемент, который проходит один итератор std::set
s end .
От cppreference.com , std::set::rbegin and std::set::crbegin
Возвращает обратный итератор для первого элемента обращенного контейнера .Это соответствует последнему элементу нереверсивного контейнера .Если контейнер пуст, возвращаемый итератор равен rend ().
std::set<int> set = { 1,2,3,4,5 };
auto iter = set.rbegin();
const int beforeEndIter = *iter;
std::cout << "--set.end() -> " << beforeEndIter << '\n';
( update ) в случае второго последнего элемента в контейнере (т.е. двапосле итератора end , используйте std :: next по той же причине, которая указана в другом ответе для std::prev
. См. Демонстрацию
std::set<int> set = {1, 2};
const bool hasElements = set.cbegin() != set.cend();
auto iter = set.rbegin();
if(hasElements && iter != set.rend()) std::cout << "--set.end() -> " << *iter << '\n';
if(hasElements && std::next(iter) != set.rend()) std::cout << "two past set.end() -> " << *std::next(iter) << '\n';
выходы :
--set.end() -> 2
two past set.end() -> 1
Второй вариант упоминался в другомответ.
С другой стороны, разыменование конечного итератора является неопределенным поведением , в котором можно ожидать любой результат.В вашем случае у вас есть последний элемент (то есть один итератор прошлого конца) контейнера.