Почему итераторы использования вместо индексов массива?

Я столкнулся с подобной проблемой. Возникла некоторая проблема со значениями по умолчанию в файле php.ini. Пожалуйста, посмотрите этот ответ , если ваша проблема не была решена с ответом, указанным выше.

226
задан Jason Baker 21 October 2008 в 21:43
поделиться

22 ответа

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

T elem = some_vector[i];

тогда, Вы делаете предположение, что контейнер имеет operator[](std::size_t) определенный. Снова, это верно для вектора, но не для других контейнеров.

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

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

199
ответ дан einpoklum - reinstate Monica 4 November 2019 в 13:27
поделиться

Я всегда использую индекс массива, потому что многие мое приложение требуют чего-то как "изображение миниатюр дисплея". Таким образом, я записал что-то вроде этого:

some_vector[0].left=0;
some_vector[0].top =0;<br>

for (int i = 1; i < some_vector.size(); i++)
{

    some_vector[i].left = some_vector[i-1].width +  some_vector[i-1].left;
    if(i % 6 ==0)
    {
        some_vector[i].top = some_vector[i].top.height + some_vector[i].top;
        some_vector[i].left = 0;
    }

}
0
ответ дан Johnsyweb 4 November 2019 в 13:27
поделиться

Во время повторения Вы не должны знать, что количество объекта обрабатывается. Вам просто нужен объект, и итераторы делают такие очень хорошие вещи.

2
ответ дан Sergey Stolyarov 4 November 2019 в 13:27
поделиться

Учась немного больше на предмет этого ответа, я понимаю, что это было определенное упрощение. Различие между этим циклом:

for (some_iterator = some_vector.begin(); some_iterator != some_vector.end();
    some_iterator++)
{
    //do stuff
}

И этот цикл:

for (int i = 0; i < some_vector.size(); i++)
{
    //do stuff
}

довольно минимально. На самом деле синтаксис выполнения циклов этот путь, кажется, растет на мне:

while (it != end){
    //do stuff
    ++it;
}

Итераторы действительно разблокировали некоторые довольно мощные декларативные функции, и, когда объединено с библиотекой алгоритмов STL можно сделать некоторые довольно прохладные вещи, которые выходят за рамки индекса массива administrivia.

3
ответ дан Jason Baker 4 November 2019 в 13:27
поделиться

Несколько положительных сторон уже. У меня есть несколько дополнительных комментариев:

  1. Принятие мы говорим о библиотеке стандарта C++, "вектор" подразумевает контейнер произвольного доступа, который имеет гарантии C-массива (произвольный доступ, contiguos расположение памяти и т.д.). Если бы Вы сказали, что 'some_container', многие вышеупомянутые ответы были бы более точными (контейнерная независимость и т.д.).

  2. Для устранения любых зависимостей от компиляторной оптимизации Вы могли переместить some_vector.size () из цикла в индексируемом коде, как так:

    const size_t numElems = some_vector.size();
    for (size_t i = 0; i 
  3. Всегда преинкрементные итераторы и постинкременты обработки как исключительные случаи.

для (some_iterator = some_vector.begin (); some_iterator! = some_vector.end (); ++ some_iterator) {//действительно наполняют}

Настолько принимающий и индексируемый std::vector<> как контейнер, нет никакого серьезного основания предпочесть один по другому, последовательно проходя контейнер. Если необходимо часто обращаться к более старым или более новым индексам elemnent, то индексируемая версия является большим количеством appropropriate.

В целом, использование итераторов предпочтено, потому что алгоритмы используют их, и поведением можно управлять (и неявно зарегистрировать) путем изменения типа итератора. Местоположения массива могут использоваться вместо итераторов, но синтаксическое различие перетерпит.

1
ответ дан user22044 4 November 2019 в 13:27
поделиться

Для контейнерной независимости

0
ответ дан John Topley 4 November 2019 в 13:27
поделиться

Вторая форма представляет то, что Вы делаете более точно. В Вашем примере Вы не заботитесь о значении меня, действительно - все, что Вы хотите, следующий элемент в итераторе.

3
ответ дан Colen 4 November 2019 в 13:27
поделиться

Итераторы STL главным образом там так, чтобы алгоритмы STL как вид могли быть контейнерным независимым политиком.

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

Это меньше вводит и легче проанализировать для большинства людей. Было бы хорошо, если бы C++ имел простой цикл foreach, не идя за борт с шаблонным волшебством.

for( size_t i = 0; i < some_vector.size(); ++i )
{
   T& rT = some_vector[i];
   // now do something with rT
}
'
6
ответ дан Jeroen Dirks 4 November 2019 в 13:27
поделиться

Я, вероятно, должен указать, что можно также звонить

std::for_each(some_vector.begin(), some_vector.end(), &do_stuff);

11
ответ дан MSalters 4 November 2019 в 13:27
поделиться

Поскольку это более объектно-ориентировано. если Вы выполняете итерации с индексом, Вы принимаете:

a), который те объекты заказаны
b), что те объекты могут быть получены индексом
c), что индексный инкремент поразит каждый объект
d), который тот индекс запускает в нуле

С итератора, Вы говорите, "дают мне все так, что я могу работать с ним", не зная, какова конкретная реализация. (В Java существуют наборы, к которым нельзя получить доступ через индекс)

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

14
ответ дан cynicalman 4 November 2019 в 13:27
поделиться

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


for(std::vector<Foo>::const_iterator pos=foos.begin(); pos != foos.end(); ++pos)
{
    // Foo & foo = *pos; // this won't compile
    const Foo & foo = *pos; // this will compile
}
14
ответ дан Pat Notz 4 November 2019 в 13:27
поделиться

Вы могли бы хотеть использовать итератор, если Вы собираетесь добавить/удалить объекты к вектору, в то время как Вы выполняете итерации по нему.

some_iterator = some_vector.begin(); 
while (some_iterator != some_vector.end())
{
    if (/* some condition */)
    {
        some_iterator = some_vector.erase(some_iterator);
        // some_iterator now positioned at the element after the deleted element
    }
    else
    {
        if (/* some other condition */)
        {
            some_iterator = some_vector.insert(some_iterator, some_new_value);
            // some_iterator now positioned at new element
        }
        ++some_iterator;
    }
}

при использовании индексов необходимо было бы переставить объекты/вниз в массиве для обработки вставок и удалений.

23
ответ дан Blacktempel 4 November 2019 в 13:27
поделиться

Разделение Проблем

очень хорошо разделить итеративный код от 'базового' беспокойства цикла. Это - почти проектное решение.

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

кроме того, в std::for_each путь, Вы ГОВОРИТЕ набор, что сделать вместо Выяснения это что-то о его внутренностях

, 0x стандарт собирается представить закрытия, которые сделают этот подход намного более простым в использовании - взглянули на выразительное питание, например, Ruby [1..6].each { |i| print i; }...

Производительность

, Но возможно проблема, за которой очень наблюдают, - то, что, с помощью for_each подход приводит к возможности параллелизировать повторение - , Intel, распараллеливающая блоки , может распределить блок кода по количеству процессоров в системе!

Примечание: после обнаружения algorithms библиотека, и особенно foreach, я прошел два или три месяца записи смехотворно маленьких структур оператора 'помощника', которые сведут Ваших поддерживающих разработчиков с ума. После этого времени я вернулся к прагматическому подходу - небольшие тела циклов не заслуживают никакого [еще 115]:)

Необходимость считанная ссылка на итераторах является книгой "Расширенный STL" .

GoF имеют крошечный небольшой абзац в конце шаблона Итератора, который говорит об этом виде повторения; это назвало 'внутренний итератор'. Взгляните здесь , также.

16
ответ дан xtofl 4 November 2019 в 13:27
поделиться

Я собираюсь быть дьяволами, защищают здесь и не рекомендуют итераторы. Главной причиной, почему, является весь исходный код, я продолжил работать от разработки Настольного приложения до разработки игр, имеют, я, и при этом я не должны были использовать итераторы. Все время они не требовались, и во-вторых скрытые предположения и путаница кода и кошмары отладки, которые Вы получаете с итераторами, делают их главным примером для не использования его в любых приложениях, которые требуют скорости.

Даже от maintence точки зрения они - путаница. Не из-за них, но из-за всего искажения, которые происходят позади сцены. Как я знаю, что Вы не реализовали свой собственный виртуальный векторный или список массива, который делает что-то совершенно другое от стандартов. Я знаю то, что тип в настоящее время теперь во время времени выполнения? Действительно ли Вы перегружали оператор, у меня не было времени для проверки всего исходного кода. Ад я даже знаю что версия STL Ваше использование?

следующей проблемой, которую Вы получили с итераторами, является текучая абстракция, хотя существуют многочисленные веб-сайты, которые обсуждают это подробно с ними.

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

26
ответ дан Chad 4 November 2019 в 13:27
поделиться

Предположите, что some_vector реализован со связанным списком. Тогда запрос объекта в месте i-th требует, чтобы я операции был сделан для пересечения списка узлов. Теперь при использовании итератора, вообще говоря, он приложит свое максимальное усилие, чтобы быть максимально эффективным (в случае связанного списка, он поддержит указатель на текущий узел и усовершенствует его в каждом повторении, требуя просто единственной операции).

, Таким образом, это обеспечивает две вещи:

  • Абстракция использования: Вы просто хотите выполнить итерации некоторых элементов, Вы не заботитесь о том, как сделать это
  • Производительность
33
ответ дан asterite 4 November 2019 в 13:27
поделиться

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

<час>, Ничего себе, это все еще получает downvoted после трех недель. Я предполагаю, что это не платит, чтобы быть немного издевательским.

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

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

50
ответ дан Mark Ransom 4 November 2019 в 13:27
поделиться

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

52
ответ дан cruizer 4 November 2019 в 13:27
поделиться

Еще лучше, чем "сообщение ЦП, что сделать" (императив), "говорит библиотекам, что Вы хотите" (функциональный).

Так вместо того, чтобы использовать циклы необходимо изучить алгоритмы, существующие в stl.

0
ответ дан Cyber Oliveira 4 November 2019 в 13:27
поделиться

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

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

for(size_t i = 0; i < myvector.size(); i++)
{
    MyClass &item = myvector[i];

    // Do stuff to "item".
}

Используя итератор может быть хорошим, если Вы думаете, что, возможно, должны были бы заменить вектор списком в какой-то момент в будущем, и это также выглядит более стильным к пятнам STL, но я не могу думать ни о какой другой причине.

5
ответ дан Adam Pierce 4 November 2019 в 13:27
поделиться

Кроме всех других превосходных ответов... int может не быть достаточно большим для Вашего вектора. Вместо этого если Вы хотите использовать индексацию, используйте size_type для Вашего контейнера:

for (std::vector<Foo>::size_type i = 0; i < myvector.size(); ++i)
{
    Foo& this_foo = myvector[i];
    // Do stuff with this_foo
}
14
ответ дан underscore_d 4 November 2019 в 13:27
поделиться

Индексирование требует дополнительной операции mul . Например, для vector v компилятор преобразует v [i] в & v + sizeof (int) * i .

3
ответ дан 23 November 2019 в 03:52
поделиться

Я не использую итераторы по той же причине, что мне не нравятся операторы foreach. При наличии нескольких внутренних циклов достаточно сложно отслеживать глобальные переменные / переменные-члены, не запоминая также все локальные значения и имена итераторов. Я считаю полезным использовать два набора индексов для разных случаев:

for(int i=0;i<anims.size();i++)
  for(int j=0;j<bones.size();j++)
  {
     int animIndex = i;
     int boneIndex = j;


     // in relatively short code I use indices i and j
     ... animation_matrices[i][j] ...

     // in long and complicated code I use indices animIndex and boneIndex
     ... animation_matrices[animIndex][boneIndex] ...


  }

Я даже не хочу сокращать такие вещи, как «animation_matrices [i]», например, до некоторого случайного «anim_matrix» с именем-итератором, потому что тогда вы не могу ясно видеть, из какого массива возникло это значение.

1
ответ дан 23 November 2019 в 03:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: