Использование итераторов над индексами массива - PullRequest
10 голосов
/ 25 марта 2010

Я просто хотел узнать, каково главное преимущество использования итераторов по сравнению с индексами массива. Я погуглил, но не получил правильного ответа.

Ответы [ 9 ]

14 голосов
/ 25 марта 2010

Полагаю, вы говорите, когда используете вектор, верно?

Основным преимуществом является то, что код итератора работает для всех контейнеров stl, а оператор индексации массива [] доступен только для векторов и запросов. Это означает, что вы можете изменить базовый контейнер, если вам нужно, без необходимости перекодировать каждый цикл. Это также означает, что вы можете поместить свой код итерации в шаблон, и он будет работать для любого контейнера, а не только для запросов и векторов (и, конечно, массивов).

6 голосов
/ 25 марта 2010

Все стандартные контейнеры обеспечивают концепцию итератора. Итератор знает, как найти следующий элемент в контейнере, особенно когда базовая структура не похожа на массив. Стиль массива operator[] не предоставляется каждым контейнером, поэтому использование привычки использовать итераторы сделает код более согласованным, независимо от выбранного контейнера.

3 голосов
/ 25 марта 2010

Вы можете абстрагировать реализацию коллекции прочь.

2 голосов
/ 25 марта 2010

STL содержит алгоритмы, такие как transform и for_each, которые работают с контейнерами. Они не принимают индексы, но используют итераторы.

Итераторы помогают скрыть реализацию контейнера и позволяют программисту сосредоточиться на алгоритме. Функцию for_each можно применять ко всему, что поддерживает прямой итератор .

2 голосов
/ 25 марта 2010

Чтобы расширить предыдущие ответы:

  1. Запись цикла с оператором [] ограничивает вас контейнером, который поддерживает [] и использует тот же тип индекса / размера. В противном случае вам нужно будет переписать каждый цикл, чтобы изменить контейнер.

  2. Даже если ваш контейнер поддерживает [], он не может быть оптимальным для последовательного перемещения. [] - это в основном оператор произвольного доступа, который для вектора равен O (1), но может быть таким же плохим, как O (n), в зависимости от базового контейнера.

  3. Это второстепенный вопрос, но если вы используете итераторы, ваш цикл может быть легче перенесен на использование стандартных алгоритмов, например, станд :: for_each.

2 голосов
/ 25 марта 2010

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

1 голос
/ 25 марта 2010

Я бы сказал, что это скорее вопрос согласованности и повторного использования кода.

  • Согласованность в том смысле, что вы будете использовать все другие контейнеры с итераторами
  • Повторное использование кода в том смысле, что алгоритмы, написанные для итераторов, не могут использоваться с оператором индекса и наоборот ... и STL имеет множество алгоритмов, поэтому вам определенно нужно его использовать.

Наконец, я хотел бы сказать, что даже C массивы имеют итераторы.

const Foo* someArray = //...
const Foo* otherArray = new Foo[someArrayLength];

std::copy(someArray, someArray + someArrayLength, otherArray);

Класс iterator_traits специализирован таким образом, что указатели или модель RandomAccessIterator.

1 голос
/ 25 марта 2010

Еще одно небольшое отличие состоит в том, что вы не можете использовать erase () для элемента в векторе по индексу, у вас должен быть итератор. Ничего страшного, так как вы всегда можете использовать «vect.begin () + index» в качестве итератора, но есть и другие соображения. Например, если вы делаете это, вы всегда должны сверять свой индекс с size (), а не с какой-то переменной, которой вы присвоили это значение.

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

1 голос
/ 25 марта 2010

Как и пункты в других ответах, итераторы также могут быть быстрее (особенно по сравнению с operator[]), так как они по сути являются итерацией по указателю. Если вы делаете что-то вроде:

for (int i = 0; i < 10; ++i)
{
    my_vector[i].DoSomething();
}

Каждая итерация цикла без необходимости вычисляет my_vector.begin() + i. Если вы используете итераторы, увеличение итератора означает, что он уже указывает на следующий элемент, поэтому вам не нужны эти дополнительные вычисления. Это мелочь, но может иметь значение в тесных петлях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...