Разница между i ++ и ++ i в цикле?

Есть ли разница в ++i и i++ в цикле for ? Это просто синтаксис?

a ++ известен как постфикс.

добавьте 1 в a, возвращает старое значение.

++ a известен как префикс.

добавьте 1 в a, возвращает новое значение.

C #:

 string[] items = {"a","b","c","d"}; int i = 0; foreach (string item in items) { Console.WriteLine(++i); } Console.WriteLine(""); i = 0; foreach (string item in items) { Console.WriteLine(i++); } 

Вывод:

 1 2 3 4 0 1 2 3 

foreach и while зависят от типа используемого вами типа инкремента. Для таких циклов, как показано ниже, не имеет значения, поскольку вы не используете возвращаемое значение i:

 for (int i = 0; i < 5; i++) { Console.Write(i);} Console.WriteLine(""); for (int i = 0; i < 5; ++i) { Console.Write(i); } 

0 1 2 3 4
0 1 2 3 4

Если используется значение, которое оценивается, тип приращения становится значительным:

 int n = 0; for (int i = 0; n < 5; n = i++) { } 

Pre-increment ++ i увеличивает значение i и оценивает новое добавочное значение.

 int i = 3; int preIncrementResult = ++i; Assert( preIncrementResult == 4 ); Assert( i == 4 ); 

Пост-инкремент i ++ увеличивает значение i и оценивает исходное значение без приращения.

 int i = 3; int postIncrementResult = i++; Assert( postIncrementtResult == 3 ); Assert( i == 4 ); 

В C ++ предварительный приращение обычно предпочтительнее, если вы можете использовать его.

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

Таким образом, в C ++, по крайней мере, может быть разница в производительности, которая будет определять ваш выбор.

В основном это проблема только в том случае, когда переменная, которая увеличивается, является пользовательским типом с переопределенным оператором ++. Для примитивных типов (int и т. Д.) Разница в производительности отсутствует. Но стоит упомянуть оператора pre-increment в качестве ориентира, если оператор пост-инкремента определенно не требуется.

Здесь есть еще одна дискуссия:
https://web.archive.org/web/20170405054235/http://en.allexperts.com/q/C-1040/Increment-operators.htm

В C ++, если вы используете STL, вы можете использовать для циклов с iteratorами. Они в основном имеют переопределенные операторы ++, поэтому прилипание к предварительному приращению – хорошая идея. Компиляторы становятся все умнее все время, но более новые могут быть способны выполнять оптимизации, которые означают, что нет разницы в производительности – особенно, если тип, увеличиваемый, определен внутри в заголовочном файле (поскольку часто используются реализации STL), чтобы компилятор мог видеть, как этот метод реализуется и может затем знать, какие оптимизации безопасны для выполнения. Тем не менее, вероятно, стоит упомянуть предварительный инкремент, потому что циклы выполняются много раз, и это означает, что вскоре можно будет усилить небольшое снижение производительности.


В других языках, таких как C #, где оператор ++ не может быть перегружен, нет разницы в производительности. Операторы pre и post increment, используемые в цикле для продвижения переменной цикла, эквивалентны.

Коррекция: допускается перегрузка ++ в C #. Кажется, что, по сравнению с C ++, в c # вы не можете перегружать версии pre и post независимо. Итак, я бы предположил, что если результат вызова ++ в C # не присваивается переменной или не используется как часть сложного выражения, тогда компилятор сократит до и после версий ++ до кода, который будет выполняться эквивалентно.

В c # нет разницы при использовании в цикле for .

 for (int i = 0; i < 10; i++) { Console.WriteLine(i); } 

выводит то же самое, что и

 for (int i = 0; i < 10; ++i) { Console.WriteLine(i); } 

Как указывали другие, при использовании в целом i ++ и ++ у меня есть тонкая, но существенная разница:

 int i = 0; Console.WriteLine(i++); // Prints 0 int j = 0; Console.WriteLine(++j); // Prints 1 

i ++ читает значение i, а затем увеличивает его.

++ i увеличивает значение i, затем читает его.

Поскольку вы спрашиваете о различии в цикле, я думаю, вы имеете в виду

 for(int i=0; i<10; i++) ...; 

В этом случае у вас нет различий в большинстве языков: цикл ведет себя одинаково независимо от того, пишете ли вы i++ и ++i . В C ++ вы можете написать свои собственные версии операторов ++, и вы можете определить для них отдельные значения, если i имеет определенный пользователем тип (например, ваш собственный class).

Причина, почему это не имеет значения выше, заключается в том, что вы не используете значение i++ . Другое дело, когда вы делаете

 for(int i=0, a = 0; i<10; a = i++) ...; 

Теперь есть разница, потому что, как указывают другие, i++ означает приращение, но оценивает предыдущее значение , но ++i означает приращение, но оценивает значение i (таким образом, оно будет оценивать новое значение). В приведенном выше случае a присваивается предыдущее значение i, а i - инкрементировано.

Вопрос в том:

Есть ли разница в ++ i и i ++ в цикле for?

Ответ: Нет .

Почему каждый ответ должен содержать подробные объяснения о до и после приращения, когда об этом даже не спрашивают?

Это для цикла:

 for (int i = 0; // Initialization i < 5; // Condition i++) // Increment { Output(i); } 

Переведет этот код без использования циклов:

 int i = 0; // Initialization loopStart: if (i < 5) // Condition { Output(i); i++ or ++i; // Increment goto loopStart; } 

Теперь имеет значение, если вы поместите i++ или ++i в Приращение здесь? Нет, это не так, поскольку возвращаемое значение операции приращения незначительно. i будет увеличиваться ПОСЛЕ выполнения кода, который находится в теле for-loop.

Как показывает этот код (см. Разборчивость MSIL в комментариях), компилятор C # 3 не делает различий между i ++ и ++ i в цикле for. Если было принято значение i ++ или ++ i, определенная разница была бы (это было скомпилировано в Visutal Studio 2008 / Release Build):

 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace PreOrPostIncrement { class Program { static int SomethingToIncrement; static void Main(string[] args) { PreIncrement(1000); PostIncrement(1000); Console.WriteLine("SomethingToIncrement={0}", SomethingToIncrement); } static void PreIncrement(int count) { /* .method private hidebysig static void PreIncrement(int32 count) cil managed { // Code size 25 (0x19) .maxstack 2 .locals init ([0] int32 i) IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: br.s IL_0014 IL_0004: ldsfld int32 PreOrPostIncrement.Program::SomethingToIncrement IL_0009: ldc.i4.1 IL_000a: add IL_000b: stsfld int32 PreOrPostIncrement.Program::SomethingToIncrement IL_0010: ldloc.0 IL_0011: ldc.i4.1 IL_0012: add IL_0013: stloc.0 IL_0014: ldloc.0 IL_0015: ldarg.0 IL_0016: blt.s IL_0004 IL_0018: ret } // end of method Program::PreIncrement */ for (int i = 0; i < count; ++i) { ++SomethingToIncrement; } } static void PostIncrement(int count) { /* .method private hidebysig static void PostIncrement(int32 count) cil managed { // Code size 25 (0x19) .maxstack 2 .locals init ([0] int32 i) IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: br.s IL_0014 IL_0004: ldsfld int32 PreOrPostIncrement.Program::SomethingToIncrement IL_0009: ldc.i4.1 IL_000a: add IL_000b: stsfld int32 PreOrPostIncrement.Program::SomethingToIncrement IL_0010: ldloc.0 IL_0011: ldc.i4.1 IL_0012: add IL_0013: stloc.0 IL_0014: ldloc.0 IL_0015: ldarg.0 IL_0016: blt.s IL_0004 IL_0018: ret } // end of method Program::PostIncrement */ for (int i = 0; i < count; i++) { SomethingToIncrement++; } } } } 

Один (++ i) является преинкрементным, один (i ++) является постинкрементом. Разница в том, какое значение немедленно возвращается из выражения.

 // Psuedocode int i = 0; print i++; // Prints 0 print i; // Prints 1 int j = 0; print ++j; // Prints 1 print j; // Prints 1 

Edit: Woops, полностью проигнорировал петлевую сторону вещей. Нет никакой реальной разницы в циклах, когда это «шаг» (для (…; …;)), но он может вступить в игру в других случаях.

Вот пример Java-образца и байтовый код, post- и preIncrement не показывают различий в Bytecode:

 public class PreOrPostIncrement { static int somethingToIncrement = 0; public static void main(String[] args) { final int rounds = 1000; postIncrement(rounds); preIncrement(rounds); } private static void postIncrement(final int rounds) { for (int i = 0; i < rounds; i++) { somethingToIncrement++; } } private static void preIncrement(final int rounds) { for (int i = 0; i < rounds; ++i) { ++somethingToIncrement; } } 

}

И теперь для байтового кода (javap -private -c PreOrPostIncrement):

 public class PreOrPostIncrement extends java.lang.Object{ static int somethingToIncrement; static {}; Code: 0: iconst_0 1: putstatic #10; //Field somethingToIncrement:I 4: return public PreOrPostIncrement(); Code: 0: aload_0 1: invokespecial #15; //Method java/lang/Object."":()V 4: return public static void main(java.lang.String[]); Code: 0: sipush 1000 3: istore_1 4: sipush 1000 7: invokestatic #21; //Method postIncrement:(I)V 10: sipush 1000 13: invokestatic #25; //Method preIncrement:(I)V 16: return private static void postIncrement(int); Code: 0: iconst_0 1: istore_1 2: goto 16 5: getstatic #10; //Field somethingToIncrement:I 8: iconst_1 9: iadd 10: putstatic #10; //Field somethingToIncrement:I 13: iinc 1, 1 16: iload_1 17: iload_0 18: if_icmplt 5 21: return private static void preIncrement(int); Code: 0: iconst_0 1: istore_1 2: goto 16 5: getstatic #10; //Field somethingToIncrement:I 8: iconst_1 9: iadd 10: putstatic #10; //Field somethingToIncrement:I 13: iinc 1, 1 16: iload_1 17: iload_0 18: if_icmplt 5 21: return } 

Нет никакой разницы, если вы не используете значение после инкремента в цикле.

 for (int i = 0; i < 4; ++i){ cout< 

Оба цикла будут печатать 0123.

Но разница возникает, когда вы используете значение после увеличения / уменьшения в вашем цикле, как показано ниже:

Pre Increment Loop:

 for (int i = 0,k=0; i < 4; k=++i){ cout< 

Выход: 0 0 1 1 2 2 3 3

Post Increment Loop:

 for (int i = 0, k=0; i < 4; k=i++){ cout< 

Выход: 0 0 1 0 2 1 3 2

Надеюсь, разница будет очевидна, если сравнить результат. Здесь указывается, что приращение / декремент всегда выполняется в конце цикла for, и, следовательно, результаты могут быть объяснены.

Да, есть. Разница заключается в возвращаемом значении. Возвращаемое значение «++ i» будет значением после увеличения i. Возврат «i ++» будет значением перед приращением. Это означает, что код выглядит следующим образом:

 int a = 0; int b = ++a; // a is incremented and the result after incrementing is saved to b. int c = a++; // a is incremented again and the result before incremening is saved to c. 

Следовательно, a будет 2, а b и c будут равны 1.

Я мог бы переписать код следующим образом:

 int a = 0; // ++a; a = a + 1; // incrementing first. b = a; // setting second. // a++; c = a; // setting first. a = a + 1; // incrementing second. 

Нет никакой реальной разницы, в обоих случаях « i » будет увеличиваться на 1.

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

 int i = 1; int a = ++i; // i is incremented by one and then assigned to a. // Both i and a are now 2. int b = i++; // i is assigned to b and then incremented by one. // b is now 2, and i is now 3 

Для ++ i и i ++ существует больше, чем циклов и различий в производительности. ++ i возвращает значение l, а i ++ возвращает r-значение. Исходя из этого, есть много вещей, которые вы можете сделать для (++ i), но не для (i ++).

 1- It is illegal to take the address of post increment result. Compiler won't even allow you. 2- Only constant references to post increment can exist, ie, of the form const T&. 3- You cannot apply another post increment or decrement to the result of i++, ie, there is no such thing as I++++. This would be parsed as ( i ++ ) ++ which is illegal. 4- When overloading pre-/post-increment and decrement operators, programmers are encouraged to define post- increment/decrement operators like: T& operator ++ ( ) { // logical increment return *this; } const T operator ++ ( int ) { T temp( *this ); ++*this; return temp; } 

В javascript из-за следующего i ++ может быть лучше использовать:

 var i=1; alert(i++); // before, 1. current, 1. after, 2. alert(i); // before, 2. current, 2. after, 2. alert(++i); // before, 2. current, 3 after, 3. 

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

При использовании i ++ следующее значение будет использовать увеличенное значение. Вы могли бы сказать, что i ++ – это способ подсчета людей, потому что вы можете начать с 0 .

Это пугает мой разум, почему люди могут писать выражение increment в for-loop как i ++.

В for-loop, когда третий компонент представляет собой простой оператор инкремента, как в

 for (i=0; i 

или

 for (i=0; i 

нет никакой разницы в результате выполнения.

Как поясняет @Jon B , в цикле for нет разницы.

Но через некоторое while или в do...while цикл, вы можете найти некоторые отличия, если вы делаете сравнение с ++i или i++

 while(i++ < 10) { ... } //compare then increment while(++i < 10) { ... } //increment then compare 

Для петель может быть разница. Это практическое применение post / pre-increment.

  int i = 0; while(i++ <= 10) { Console.Write(i); } Console.Write(System.Environment.NewLine); i = 0; while(++i <= 10) { Console.Write(i); } Console.ReadLine(); 

В то время как первый из них считается равным 11, а циклов - 11 раз, второй - нет.

В основном это довольно удобно использовать в то время как (x--> 0); - - Loop для итерации, например, всех элементов массива (исключая здесь foreach-constructs).

Они оба увеличивают число. ++i эквивалентно i = i + 1 .

i++ и ++i очень похожи, но не совсем то же самое. Оба увеличивают число, но ++i увеличивает число до вычисления текущего выражения, тогда как i++ увеличивает число после вычисления выражения.

 int i = 3; int a = i++; // a = 3, i = 4 int b = ++a; // b = 4, a = 

Проверьте эту ссылку .

Да, существует разница между ++i и i++ в цикле for , хотя в необычных случаях использования; когда переменная цикла с оператором increment / decment используется в блоке for или внутри тестового выражения цикла или с одной из переменных цикла . Нет, это не просто синтаксис.

Поскольку i в коде означает вычисление выражения i а оператор не означает оценку, а просто операцию;

  • ++i означает значение приращения i на 1, а затем оценку i ,
  • i++ означает оценку i и более позднего значения приращения i на 1.

Итак, то, что получается из каждых двух выражений, отличается тем, что оценивается в каждом из них. Все то же самое для --i и i--

Например;

 let i = 0 i++ // evaluates to value of i, means evaluates to 0, later increments i by 1, i is now 1 0 i 1 ++i // increments i by 1, i is now 2, later evaluates to value of i, means evaluates to 2 2 i 2 

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

 for(i=0, j=i; i<10; j=++i){ console.log(j, i) } for(i=0, j=i; i<10; j=i++){ console.log(j, i) } 

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

Кроме того, в c++ обычно безопаснее использовать форму предварительного приращения ( ++i ), потому что ее легче оптимизировать. (Скотт Лэнгхэм избил меня до этого лакомого кусочка . Проклятье, Скотт)

Я не знаю других языков, но в Java ++ i является приращением префикса, что означает: увеличить i на 1, а затем использовать новое значение i в выражении, в котором я проживаю, а i ++ – это приращение постфикса, что означает следующее: : используйте текущее значение i в выражении, а затем увеличьте его на 1. Пример:

 public static void main(String [] args){ int a = 3; int b = 5; System.out.println(++a); System.out.println(b++); System.out.println(b); 

}, а выход:

  • 4
  • 5
  • 6

i ++; ++ i; оба они похожи, так как они не используются в выражении.

 class A { public static void main (String []args) { int j = 0 ; int k = 0 ; ++j; k++; System.out.println(k+" "+j); }} prints out : 1 1 
Давайте будем гением компьютера.