Крайне необычный способ разыменования итератора

Итераторы занимают важное место в разработке программ на С++. Но многие начинающие программисты совершенно не понимают, как ими пользоваться. И иногда рождают такой код, от которого волосы встают дыбом. Ниже приводится пример такого кода для задачи получения значения, на которое указывает итератор.

Есть несколько переменных:

std::vector<int> vec;
std::vector<int>::iterator it;
int value;

Нужно записать в переменную value значение, на которое указывает итератор it. Вроде бы ничего сложного. Но оказывается не для всех. Однажды я увидел вот такое решение данной задачи:

value = vec[std::distance(vec.begin(), it)]

Этот код работает. Но, во-первых, он труден для понимания и написания (по сравнению с правильным решением). И, во-вторых, в нем делается много лишней работы. Давайте разберем, как он работает.

std::distance(vec.begin(), it)

Здесь происходит вычисление разницы между итератором it, указывающим на нужный нам элемент, и начальным итератором, указывающим на первый элемент контейнера. При этом нам приходится создавать начальный итератор. По сути здесь вычисляется индекс нужного нам элемента в контейнере (обозначим его как index). Дальше этот индекс используется для получения элемента по его порядковому номеру в контейнере.

value = vec[index]

Таким образом здесь происходит:
1. Создание начального итератора с вызовом его конструктора в методе begin.
2. Вызов функции std::distance для вычисления индекса.
3. Уничтожение начального итератора с вызовом его деструктора.
4. Вызов оператора [] для std::vector<int>, который и возвращает нужное нам значение.

Ниже приводится правильный способ разыменования итератора.

value = *it

Обратите внимание: он не только намного проще исходного варианта, но и в нем не делается никакой лишней работы. Всё что здесь происходит так это вызов оператора * для типа итератора. Всё. Никакие дополнительные объекты не создаются.

Итераторы — мощный инструмент, но ими тоже надо уметь пользоваться.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *