Итератор на последний элемент 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 шт):
Функция end возвращает итератор, который указывает на условный элемент, находящийся за последним, а не на последний. Ошибка возникает не там, где вы указываете, а на следующей строке.
std::cout << *my_iter; //этот элемент не существует
Чтобы вывести последний элемент, надо уменьшить итератор на единицу:
std::cout << *std::prev(my_iter);
А зачем вообще такое нужно ?? Зачем возвращать итератор на несуществующий элемент ?
Есть несколько применений такого итератора.
- Определение размера контейнера или части контейнера. Размер можно найти простым вычитанием двух итераторов:
size = end - begin;, либо, если итератор конкретного контейнера не поддерживает операцию вычитания, то с помощью функцииstd::distance(begin, end);. - Обход контейнера в цикле. Для обхода обычно пишут такой цикл:
for (auto it = container.begin(); it < container.end(); it++) {...}
- Для возврата ошибочного результата в некоторых функциях 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 Строго говоря, определение этой функции немного не такое: она ищет первый элемент больше заданного. Просто здесь мне кажется, что так легче объяснить.