Почему элемент end () в ассоциативном контейнере печатает то же значение, что и последний элемент? [дубликат]

Dec 10 2020

В приведенном ниже коде значение, на которое указывает итератор, одинаково как для последнего, так и для второго последнего элемента.

#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;
}

Насколько я понимаю, значение, на которое указывает конечный элемент, должно быть нулевым. Почему это так?

Ответы

6 TonyTannous Dec 10 2020 at 20:53

Вы вызвали неопределенное поведение, std :: set :: end

Возвращает итератор к элементу, следующему за последним элементом набора. Этот элемент действует как заполнитель; попытка получить к нему доступ приводит к неопределенному поведению.


Неопределенное поведение делает всю программу бессмысленной.

1 largest_prime_is_463035818 Dec 10 2020 at 20:55

Насколько я понимаю, значение, на которое указывает конечный элемент, должно быть нулевым. Почему это так?

Почему ваше понимание неверно, я не могу сказать;). Если не считать придирчивости: Нет. Нет никакого "конечного элемента". В endитератор указывает на один мимо последнего элемента. Вы не можете разыменовать его. Если вы это сделаете, вы вызовете неопределенное поведение.

Последний элемент в контейнере обычно называют «задним», и у многих контейнеров есть back()метод доступа к нему.

AsteroidsWithWings Dec 10 2020 at 21:01

Насколько я понимаю, значение, на которое указывает конечный элемент, должно быть нулевым. Почему это так?

Это не так.

Итератор «за один конец» ни на что не «указывает»; это не разыменовывается.

C-строки могут сначала показаться исключением из этого правила, но это не так: они логически завершаются NULLсимволом, который вы можете проверить, но NULLон все еще является частью массива charобъектов, и вы не можете разыменовать char*это последний итератор для этого массива. Думайте о нулевом ограничителе C-строки как о «этой странице, которая намеренно оставлена ​​пустой»; страница больше не дает вам истории, но это все еще страница.

Почему элемент end () в ассоциативном контейнере печатает то же значение, что и последний элемент?

Это один из возможных результатов программы с неопределенным поведением.