Итератор на последний элемент std::deque

Непонятная ошибка при получении итератора на последний элемент очереди. Вот такой просто код:

#include <iostream>
#include <deque>


int main
{
    std::deque<int>my_deque;

    my_deque.push_back(1);
    my_deque.push_back(2);

    std::deque<int>::iterator my_iter = my_deque.end();   //Ошибка: cannot dereference out of range deque iterator

    std::cout << *my_iter;    
}

cannot dereference out of range deque iterator

невозможно разыменовать итератор deque вне диапазона

Но почему ? Что нет так ?


Ответы (1 шт):

Автор решения: maestro

Функция end возвращает итератор, который указывает на условный элемент, находящийся за последним, а не на последний. Ошибка возникает не там, где вы указываете, а на следующей строке.

std::cout << *my_iter; //этот элемент не существует

Чтобы вывести последний элемент, надо уменьшить итератор на единицу:

std::cout << *std::prev(my_iter);

А зачем вообще такое нужно ?? Зачем возвращать итератор на несуществующий элемент ?

Есть несколько применений такого итератора.

  1. Определение размера контейнера или части контейнера. Размер можно найти простым вычитанием двух итераторов: size = end - begin;, либо, если итератор конкретного контейнера не поддерживает операцию вычитания, то с помощью функции std::distance(begin, end);.
  2. Обход контейнера в цикле. Для обхода обычно пишут такой цикл:
for (auto it = container.begin(); it < container.end(); it++) {...}
  1. Для возврата ошибочного результата в некоторых функциях stl. Например, функция std::find возвращает end, если искомый элемент в контейнере не найден.

Следует ещё отметить, что есть в stl есть функции поиска, которые возвращают итератор не на найденный элемент, а на тот, который находится сразу за искомым. Таковым может быть и итератор end. Например, функция std::upper_bound ищет в контейнере начиная с некоторого итератора одинаковые элементы, и возвращает итератор, который следует сразу за последним одинаковым элементом1. Почему не на последний? См. п. 1. Вот пример использования:

const std::vector<int> data = {5, 5, 5, 6 };
auto it = std::upper_bound(data.begin(), data.end(), 5); //ищем итератор на элемент, который находится сразу за пятёркой
size_t fives_count = std::distance(data.begin(), it);

1 Строго говоря, определение этой функции немного не такое: она ищет первый элемент больше заданного. Просто здесь мне кажется, что так легче объяснить.

→ Ссылка