Инициализация итератора

vector<int> m={1,2,3};
m.begin()++;
cout<<m[0];}

Вопрос, почему не изменяется значение итератора на 0-й элемент?


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

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

Рассмотрим код

int a = 5;
int * p = &a;

Ds ощущаете разницу между

(*p)++;

и

p++;

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

Вот примерно то же самое и с итераторами: итератор по сути аналог указателя.

→ Ссылка
Автор решения: αλεχολυτ

Что делает m.begin() - возвращает итератор (т.е. экземпляр типа iterator для специфического типа вектора). Этот итератор представляет собой новый безымянный объект, значение которого указывает на начало вектора m.

Далее ++ выполняет постинкремент этого безымянного объекта. После ; этот объект перестаёт существовать.

m.begin()++;
           ^--- безымянный объект, для которого был выполнен инкремент, умирает

Дальнейший вывод m[0] представляет собой вызов operator[] для вектора, который перегружен для предоставления доступа к элементам по индексу. В данном случае там (по индексу 0) расположена 1, которой проинициализирован в первой строке начальный элемент массива. Этот вывод вообще никак не связан с выполненным ранее инкрементом безымянного объекта итератора, который был получен строкой выше.


Если хочется вывести значение через итератор, и при этом, чтобы был выведен следующий элемент массива, можно написать так:

auto it = m.begin() + 1;
cout << *it;              // выведет 2 (т.е. элемент m[1])

Или однострочник:

cout << *(m.begin() + 1);

Если нужно изменить непосредственно сам элемент m[0], то надо выполнить инкремент после разыменования итератора:

(*m.begin())++;
cout << m[0];              // выведет 2 (т.е. увеличенный элемент m[0])

Для однострочного варианта, чтобы значение сразу стало наблюдаемым, постинкремент следует заменить преинкрементом:

cout << ++*m.begin();
→ Ссылка