Я столкнулся с подобной проблемой. Возникла некоторая проблема со значениями по умолчанию в файле php.ini. Пожалуйста, посмотрите этот ответ , если ваша проблема не была решена с ответом, указанным выше.
Первая форма эффективна, только если vector.size () является быстрой операцией. Это верно для векторов, но не для списков, например. Кроме того, что Вы планируете сделать в теле цикла? Если Вы планируете доступ к элементам как в
T elem = some_vector[i];
тогда, Вы делаете предположение, что контейнер имеет operator[](std::size_t)
определенный. Снова, это верно для вектора, но не для других контейнеров.
использование итераторов приближают Вас к контейнерной независимости. Вы не делаете предположения о способности произвольного доступа или быстро size()
операция, только что контейнер имеет возможности итератора.
Вы могли улучшить свой код далее при помощи стандартных алгоритмов. В зависимости от того, что это, Вы пытаетесь достигнуть, можно выбрать использовать std::for_each()
, std::transform()
и так далее. При помощи стандартного алгоритма, а не явного цикла Вы стараетесь не перестраивать колесо. Ваш код, вероятно, будет более эффективным (учитывая правильный алгоритм, выбран), корректный и допускающий повторное использование.
Я всегда использую индекс массива, потому что многие мое приложение требуют чего-то как "изображение миниатюр дисплея". Таким образом, я записал что-то вроде этого:
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;
}
}
Во время повторения Вы не должны знать, что количество объекта обрабатывается. Вам просто нужен объект, и итераторы делают такие очень хорошие вещи.
Учась немного больше на предмет этого ответа, я понимаю, что это было определенное упрощение. Различие между этим циклом:
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.
Несколько положительных сторон уже. У меня есть несколько дополнительных комментариев:
Принятие мы говорим о библиотеке стандарта C++, "вектор" подразумевает контейнер произвольного доступа, который имеет гарантии C-массива (произвольный доступ, contiguos расположение памяти и т.д.). Если бы Вы сказали, что 'some_container', многие вышеупомянутые ответы были бы более точными (контейнерная независимость и т.д.).
Для устранения любых зависимостей от компиляторной оптимизации Вы могли переместить some_vector.size () из цикла в индексируемом коде, как так:
const size_t numElems = some_vector.size(); for (size_t i = 0; i
Всегда преинкрементные итераторы и постинкременты обработки как исключительные случаи.
Настолько принимающий и индексируемый std::vector<>
как контейнер, нет никакого серьезного основания предпочесть один по другому, последовательно проходя контейнер. Если необходимо часто обращаться к более старым или более новым индексам elemnent, то индексируемая версия является большим количеством appropropriate.
В целом, использование итераторов предпочтено, потому что алгоритмы используют их, и поведением можно управлять (и неявно зарегистрировать) путем изменения типа итератора. Местоположения массива могут использоваться вместо итераторов, но синтаксическое различие перетерпит.
Вторая форма представляет то, что Вы делаете более точно. В Вашем примере Вы не заботитесь о значении меня, действительно - все, что Вы хотите, следующий элемент в итераторе.
Итераторы STL главным образом там так, чтобы алгоритмы STL как вид могли быть контейнерным независимым политиком.
, Если Вы просто хотите циклично выполниться по всем записям в векторе просто, используют индексный стиль цикла.
Это меньше вводит и легче проанализировать для большинства людей. Было бы хорошо, если бы C++ имел простой цикл foreach, не идя за борт с шаблонным волшебством.
for( size_t i = 0; i < some_vector.size(); ++i )
{
T& rT = some_vector[i];
// now do something with rT
}
'
Я, вероятно, должен указать, что можно также звонить
std::for_each(some_vector.begin(), some_vector.end(), &do_stuff);
Поскольку это более объектно-ориентировано. если Вы выполняете итерации с индексом, Вы принимаете:
a), который те объекты заказаны
b), что те объекты могут быть получены индексом
c), что индексный инкремент поразит каждый объект
d), который тот индекс запускает в нуле
С итератора, Вы говорите, "дают мне все так, что я могу работать с ним", не зная, какова конкретная реализация. (В Java существуют наборы, к которым нельзя получить доступ через индекс)
кроме того, с итератором, никакая потребность волноваться о движении за пределы массива.
Другая хорошая вещь об итераторах состоит в том, что они лучше позволяют Вам выражать (и осуществлять) Ваше предпочтение константы. Этот пример гарантирует, что Вы не будете изменять вектор посреди своего цикла:
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
}
Вы могли бы хотеть использовать итератор, если Вы собираетесь добавить/удалить объекты к вектору, в то время как Вы выполняете итерации по нему.
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;
}
}
при использовании индексов необходимо было бы переставить объекты/вниз в массиве для обработки вставок и удалений.
очень хорошо разделить итеративный код от 'базового' беспокойства цикла. Это - почти проектное решение.
Действительно, выполняя итерации индексом связывает Вас с реализацией контейнера. При выяснении у контейнера начальный и конечный итератор, включает код цикла для использования с другими контейнерными типами.
кроме того, в std::for_each
путь, Вы ГОВОРИТЕ набор, что сделать вместо Выяснения это что-то о его внутренностях
, 0x стандарт собирается представить закрытия, которые сделают этот подход намного более простым в использовании - взглянули на выразительное питание, например, Ruby [1..6].each { |i| print i; }
...
, Но возможно проблема, за которой очень наблюдают, - то, что, с помощью for_each
подход приводит к возможности параллелизировать повторение - , Intel, распараллеливающая блоки , может распределить блок кода по количеству процессоров в системе!
Примечание: после обнаружения algorithms
библиотека, и особенно foreach
, я прошел два или три месяца записи смехотворно маленьких структур оператора 'помощника', которые сведут Ваших поддерживающих разработчиков с ума. После этого времени я вернулся к прагматическому подходу - небольшие тела циклов не заслуживают никакого [еще 115]:)
Необходимость считанная ссылка на итераторах является книгой "Расширенный STL" .
GoF имеют крошечный небольшой абзац в конце шаблона Итератора, который говорит об этом виде повторения; это назвало 'внутренний итератор'. Взгляните здесь , также.
Я собираюсь быть дьяволами, защищают здесь и не рекомендуют итераторы. Главной причиной, почему, является весь исходный код, я продолжил работать от разработки Настольного приложения до разработки игр, имеют, я, и при этом я не должны были использовать итераторы. Все время они не требовались, и во-вторых скрытые предположения и путаница кода и кошмары отладки, которые Вы получаете с итераторами, делают их главным примером для не использования его в любых приложениях, которые требуют скорости.
Даже от maintence точки зрения они - путаница. Не из-за них, но из-за всего искажения, которые происходят позади сцены. Как я знаю, что Вы не реализовали свой собственный виртуальный векторный или список массива, который делает что-то совершенно другое от стандартов. Я знаю то, что тип в настоящее время теперь во время времени выполнения? Действительно ли Вы перегружали оператор, у меня не было времени для проверки всего исходного кода. Ад я даже знаю что версия STL Ваше использование?
следующей проблемой, которую Вы получили с итераторами, является текучая абстракция, хотя существуют многочисленные веб-сайты, которые обсуждают это подробно с ними.
Извините, я не имею и все еще не видел точки в итераторах. Если они абстрагируют список или вектор далеко от Вас, когда на самом деле уже необходимо знать, какой вектор или перечисляют контакт с тем, если Вы не делаете тогда своей просто попытки собраться для некоторых больших сеансов отладки в будущем.
Предположите, что some_vector реализован со связанным списком. Тогда запрос объекта в месте i-th требует, чтобы я операции был сделан для пересечения списка узлов. Теперь при использовании итератора, вообще говоря, он приложит свое максимальное усилие, чтобы быть максимально эффективным (в случае связанного списка, он поддержит указатель на текущий узел и усовершенствует его в каждом повторении, требуя просто единственной операции).
, Таким образом, это обеспечивает две вещи:
Это - часть современного процесса идеологической обработки C++. Итераторы являются единственным способом выполнить итерации большинства контейнеров, таким образом, Вы используете его даже с векторами только для получения в надлежащее мышление. Серьезно, это - единственная причина, я делаю это - я не думаю, что когда-либо заменял вектор другим видом контейнера.
<час>, Ничего себе, это все еще получает downvoted после трех недель. Я предполагаю, что это не платит, чтобы быть немного издевательским.я думаю, что индекс массива более читаем. Это соответствует синтаксису, используемому на других языках и синтаксисе, используемом для старомодных массивов C. Это является также менее подробным. Эффективность должна быть промывкой, если Ваш компилятор хорошо работает, и существуют едва любые случаи, где это имеет значение так или иначе.
, Несмотря на это, я все еще часто использую итераторы с векторами. Я полагаю, что итератор является важным понятием, таким образом, я продвигаю его каждый раз, когда я могу.
потому что Вы не связываете свой код с конкретной реализацией списка some_vector. при использовании индексов массива это должна быть некоторая форма массива; при использовании итераторов, можно использовать тот код любой реализации списка.
Еще лучше, чем "сообщение ЦП, что сделать" (императив), "говорит библиотекам, что Вы хотите" (функциональный).
Так вместо того, чтобы использовать циклы необходимо изучить алгоритмы, существующие в stl.
Я не думаю, что это имеет много значения для вектора. Я предпочитаю использовать индекс сам, поскольку я полагаю, что он более читаем, и можно сделать произвольный доступ как переходящий вперед 6 объектов или переходящий назад если потребности быть.
мне также нравится делать ссылку на объект в цикле как это, таким образом, нет большого количества квадратных скобок вокруг места:
for(size_t i = 0; i < myvector.size(); i++)
{
MyClass &item = myvector[i];
// Do stuff to "item".
}
Используя итератор может быть хорошим, если Вы думаете, что, возможно, должны были бы заменить вектор списком в какой-то момент в будущем, и это также выглядит более стильным к пятнам STL, но я не могу думать ни о какой другой причине.
Кроме всех других превосходных ответов... 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
}
Индексирование требует дополнительной операции mul
. Например, для vector
компилятор преобразует v [i]
в & v + sizeof (int) * i
.
Я не использую итераторы по той же причине, что мне не нравятся операторы 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» с именем-итератором, потому что тогда вы не могу ясно видеть, из какого массива возникло это значение.