Важность итераторов в C ++ - PullRequest
2 голосов
/ 23 марта 2012

Это может показаться странным вопросом, но сегодня я разговаривал с другом, который разглагольствовал о сегодняшних программистах на C ++ и о том, что они просто не делают все правильно. Он сказал, что его главная любимая мозоль - злоупотребление итерацией в коде, подобном следующему:

for(int i = 0; i<((int) someVector.size()); ++i){
    //Something here
}

вместо более традиционного

vector::iterator i;
for(i = someVector.begin(); i!=someVector.end(); ++i){
    //Something here
}

Хотя я понимаю оба метода, есть ли какая-то конкретная причина, почему второй превосходит первый? Это производительность? Или какой-то другой фактор?

Заранее спасибо.

Ответы [ 5 ]

3 голосов
/ 23 марта 2012

Ни один из них не является хорошим стилем.

Первый имеет бесполезное и опасное приведение.

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

Лучше:

using std::begin, std::end;
for( auto it = begin(container), end_it = end(container); it != end_it; ++it )

Это работает с любым контейнером STL, массивами и любым контейнеромвы предоставляете вспомогательные функции begin и end.

1 голос
/ 23 марта 2012

Для vector разница между ними невелика. Однако, если вы хотите перебрать структуру данных, такую ​​как set, которая вообще не имеет произвольного доступа, тогда второй вариант с использованием итераторов будет единственным разумным выбором.

Стандартная библиотека C ++ делает все возможное, чтобы интерфейс "итератора" был как можно более согласованным для многих различных типов контейнеров.

0 голосов
/ 23 марта 2012

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

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

for (auto i : someVector)
    // ... 

В большинстве случаев, однако, это должнобыть в реализации алгоритма.

0 голосов
/ 23 марта 2012

Реальное увеличение производительности при использовании итератора, как правило, отсутствует. Возможно меньше. Однако у них есть несколько потенциальных преимуществ по сравнению с «методом C» итерации:

1) Потенциально проще абстрагировать контейнер с помощью итератора. Поскольку мы имеем дело с указателем на каждой итерации, если тип контейнера должен измениться и получить доступ к элементу путем изменения индекса в форме (или даже невозможно, потому что произвольный доступ невозможен), итератор может сохранить некоторые утомительные изменения. 1003 *

2) Вы можете избежать использования size() каждой итерации. Несмотря на то, что вы могли бы рассчитать его один раз, лучше все же избежать этого.

3) По сути, вы имеете дело с указателем на каждый элемент контейнера, через который вы перебираете. Это лучше (по крайней мере, мне так кажется) и, возможно, более компактно, чем индекс.

0 голосов
/ 23 марта 2012

В некоторых структурах данных вычисление размера может быть неэффективным.В зависимости от того, сколько может оптимизатор сделать, это может в конечном итоге вызвать метод size () для каждой итерации цикла.Когда вы используете второй фрагмент кода, вы не полагаетесь на вызов метода для вычисления размера, когда все, что вам действительно нужно, это узнать, достиг ли вы конца.

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

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