В приведенном ниже коде значение, на которое указывает итератор, одинаково и для последнего, и для предпоследнего элемента.
#include <iostream>
#include <set>
using namespace std;
int main()
{
set<int> s1 = {4,3,2,5,1};
set<int>::iterator i;
i = s1.end();
cout << *i << endl; // 5
i--;
cout << *i << endl; // 5
cout << *s1.end() << endl; // 5
cout << *(--s1.end()) << endl; // 5
return 0;
}
Насколько я понимаю, значение, на которое указывает конечный элемент, должно быть нулевым. Почему это так?
Цель для vector
, но на самом деле это одно и то же, в ассоциативных контейнерах нет ничего особенного.
Вы вызвали неопределенное поведение, std::set::end
Возвращает итератор к элементу, следующему за последним элементом набор. Этот элемент действует как заполнитель; попытка доступа к нему приводит к неопределенное поведение.
Неопределенное поведение делает всю программу бессмысленной.
Насколько я понимаю, значение, на которое указывает конечный элемент, должно быть нулевым. Почему это так?
Почему ваше понимание неверно, я не могу сказать ;). Язвенность в сторону: нет. Нет никакого «конечного элемента». Итератор end
указывает на один после последнего элемента. Вы не можете разыменовать его. Если вы это сделаете, вы вызовете неопределенное поведение.
Последний элемент в контейнере обычно называют «задним», и многие контейнеры имеют метод back()
для доступа к нему.
Насколько я понимаю, значение, на которое указывает конечный элемент, должно быть нулевым. Почему это так?
Это не так.
Итератор «один после конца» ни на что не «указывает»; это не разыменуемо.
На первый взгляд может показаться, что C-строки являются исключением из этого правила, но это не так: они логически заканчиваются символом NULL
, который вы можете проверить, но этот NULL
все еще является частью массива объектов char
, и вы не может разыменовать char*
, который является итератором, идущим за концом для этого массива. Думайте о нулевом терминаторе C-строки как о «этой странице, намеренно оставленной пустой»; страница не дает вам больше истории, но это все еще страница.
Почему элемент end() в ассоциативном контейнере печатает то же значение, что и последний элемент?
Это один из возможных результатов программы с неопределенным поведением.
«В моем понимании значение, на которое указывает конечный элемент, должно быть нулевым» - даже если бы это было правдой (что не так), разыменование нулевого указателя вызывает неопределенное поведение