Увеличивающиеся итераторы: ++ эффективнее, чем ++? [Дубликат]

Possible Duplicate:
Is there a performance difference between i++ and ++i in C++?

Я пишу программу, в которой итератор используется для цикла по std :: vector. Кто-то сказал мне, что выполнение ++ в выражении for приводит к более эффективному коду. Другими словами, они говорят, что:

for ( vector<string>::iterator it=my_vector.begin(); it != my_vector.end(); ++it )

работает быстрее чем

for ( vector<string>::iterator it=my_vector.begin(); it != my_vector.end(); it++ )

Это правда? Если да, то в чем причина повышения эффективности? Все, что он делает ++ / ++, - это перемещает итератор к следующему элементу в векторе, не так ли?

 macbirdie03 июл. 2009 г., 00:52
Точная копия, но реп-гонка в любом случае.
 Shog9♦03 июл. 2009 г., 00:48
 Johannes Schaub - litb03 июл. 2009 г., 00:55
Это касается итераторов, и ответы должны быть такими же. Другие вопросы, кажется, задают об общей разнице. Я думаю, что это связанные вопросы, но не точные дубликаты?
 Johannes Schaub - litb03 июл. 2009 г., 01:21
Тем не менее, я согласен с вами, похоже, что нет разницы, когда он только спрашивает об эффективности. Похоже на дурака! :)
 Shog9♦03 июл. 2009 г., 01:00
@litb: сложный вызов ... Другой вопрос касается специфических для C ++ различий в производительности между двумя операторами, и ответы отражают это при обсуждении того, как реализация объекта может потенциально привести к таким несоответствиям. Итераторы являются (или могут быть) объектами; так что это действительно подмножество предыдущего вопроса.

Ответы на вопрос(7)

потому что ему ++ нужно вернуть копию объекта, а затем увеличить саму себя.

по которой преинкремент быстрее, заключается в том, что постинкремент должен сделать копию старого значения для возврата. КакПОЛУЧИЛО № 2 иными словами, «Преинкремент более эффективен, чем постинкремент, потому что для постинкремента объект должен сам себя увеличивать, а затем возвращать временное значение, содержащее его старое значение. Обратите внимание, что это верно даже для встроенных функций, таких как int. & Quot;

ПОЛУЧИЛО № 55 предоставляет каноническую форму постинкремента, которая показывает, что он должен выполнять преинкремент плюс еще немного работы:

T T::operator++(int)
{
  T old( *this ); // remember our original value
  ++*this;        // always implement postincrement
                  //  in terms of preincrement
  return old;     // return our original value
}

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

 03 июл. 2009 г., 00:47
Обратите внимание, что приличные компиляторы будут оптимизировать копию старого значения, если оно никогда не будет использовано.
 03 июл. 2009 г., 00:54
Но вы можете предположить, что прединкремент по крайней мере так же эффективен, как постинкремент. Так почему бы просто не использовать его всегда, когда они в противном случае эквивалентны?
 03 июл. 2009 г., 00:49
Точно: вы не можете обещать, что предварительное добавление более эффективно, чем постинкрементное, потому что (а) стандарт не требует этого и (б) довольно легко изобрести комбинации исходного кода и компилятора, где оба одинаково эффективны.
 03 июл. 2009 г., 01:02
Согласовано: я думаю, что используйте preincrement, где это возможно, поскольку я не могу придумать законную причину, по которой он будет хуже, чем post. Если какой-то класс перегружает оба оператора (плохо) и каким-то образом ухудшает предварительный инкремент, то вызывающего абонента нельзя обвинить в том, что он не обошел его. Я просто не думаю, что нужно обещать, что он "более эффективен" (который многие будут читать как «строго более эффективный»), когда такой гарантии нет, и, как правило, они идентичны в оптимизированном коде.

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

Векторные итераторы, вероятно, являются "просто указателями" (в оптимизированных сборках без отладки), и обаoperator++с будут встроены. Поскольку возвращаемое значение не используется, копия обычно удаляется. Так что это ничего не изменит. Я имею привычку печатать++it так как:

1) Однажды это может иметь значение для некоторого типа итератора, и я не хочу делать что-то особенное для этого типа.

2) Лично я считаю, что префиксный оператор более четко выражает намерение: «увеличить его», а не «использовать, а затем увеличить».

 18 авг. 2017 г., 22:46
Я полагаю, что я должен записаться до плохих учителей в старшей школе, прежде чем я уйду в колледж. Они сказали нам ++, я имел в виду, что он будет увеличиваться до оценки того, что находится внутри цикла, а i ++ будет увеличиваться после оценки того, что внутри цикла. Если бы мне сказали правильно с самого начала, путаницы никогда бы не было.
 18 авг. 2017 г., 11:09
@Josh: хорошо, но это всего лишь следствие полной путаницы новичка в отношении того, когда выполняется последняя часть цикла for. Конечно, вы по-прежнему инициализируете в 0, и он по-прежнему имеет значение 0 в первый раз в цикле, 1 во второй раз и т. Д., Независимо от того, пишете ли вы++i или жеi++, Честно говоря, если писать++i предлагает новичку скорее разрешить эту путаницу, а не позже, и понять, что предложение выполненоafter тело цикла независимо от того, что в нем находится, тогда я буду оценивать его как дополнительное преимущество для++i!
 15 авг. 2017 г., 21:39
Я должен сказать, что номер 2 для меня было более запутанным, чтобы увидеть ++ это, чем это ++. Например, глядя на обычный цикл int for, for (int i = 0; i & lt; 10; i ++) говорит мне, что у меня есть целое число i, которое я установил в 0 (специально, потому что я хочу, чтобы оно было 0 в первый раз), Я хочу сделать это до тех пор, пока я меньше 10, и я хочу увеличивать i на ОДИН каждый раз после завершения цикла). чтобы увидеть ++, это было очень странно для меня в первый раз, я помню, как подумал (почему вы хотите повторять ПЕРЕД выполнением чего-либо? почему бы вам просто не установить то, что вы хотите, а не на 1 меньше, чем то, что вы хотите? ). Я понял это сейчас, но все еще

++ он более эффективен, чем ++, потому что он ++ создает временный объект, а ++ - нет.

Также в C ++ есть вероятность, что кто-то перегружен оператором постинкремента.

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

it++ выполняет следующие операции:

create a copy of it increment it return the original (non-incremented) it

++it выполняет следующие операции:

increment it return it

Так какit++ создает копию, можно сказать, "медленнее". Однако любой достойный компилятор оптимизирует эту разницу для большинства определенных типов. Для некоторых пользовательских типов этоcan будь быстрее

 02 мая 2016 г., 21:58
Вы имели в виду "медленнее"?

std :: vector & lt; & gt; (и другие std-итераторы) он, скорее всего, будет оптимизирован, чтобы быть таким же.

Ваш ответ на вопрос