Разница между я ++ и ++ я в цикле?
Есть ли разница в ++i
и i++
в цикле for
? Это просто синтаксис?
Ответы
Ответ 1
a ++ известен как постфикс.
добавить 1 в a, возвращает старое значение.
++ a известен как префикс.
добавить 1 в a, возвращает новое значение.
С#:
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++) { }
Ответ 2
Pre-increment ++i увеличивает значение я и оценивает новое добавочное значение.
int i = 3;
int preIncrementResult = ++i;
Assert( preIncrementResult == 4 );
Assert( i == 4 );
Post-increment i++ увеличивает значение я и оценивает исходное значение без приращения.
int i = 3;
int postIncrementResult = i++;
Assert( postIncrementtResult == 3 );
Assert( i == 4 );
В C++ предварительный приращение обычно предпочтительнее, если вы можете использовать его.
Это связано с тем, что если вы используете пост-инкремент, это может потребовать от компилятора генерировать код, создающий дополнительную временную переменную. Это связано с тем, что как предыдущие, так и новые значения изменяемой переменной необходимо удерживать где-то, потому что они могут понадобиться в другом месте в оцениваемом выражении.
Таким образом, по крайней мере, в C++ может быть разница в производительности, которая поможет вам выбрать, какой из них использовать.
В основном это проблема только в том случае, когда переменная, которая увеличивается, является пользовательским типом с переопределенным оператором ++. Для примитивных типов (int и т.д.) Нет разницы в производительности. Но стоит упомянуть оператора pre-increment в качестве ориентира, если оператор post-increment определенно не требуется.
Там еще несколько обсуждений:
https://web.archive.org/web/20170405054235/http://en.allexperts.com/q/C-1040/Increment-operators.htm
В C++, если вы используете STL, вы можете использовать для циклов с итераторами. Они в основном имеют переопределенные операторы ++, поэтому прилипание к предварительному приращению - хорошая идея. Компиляторы становятся все умнее все время, но более новые могут быть способны выполнять оптимизацию, что означает отсутствие разницы в производительности - особенно, если увеличиваемый тип определяется встроенным в заголовочный файл (как часто реализуются STL-реализации), чтобы компилятор мог видеть, как этот метод реализуется и может затем знать, какие оптимизации безопасны для выполнения. Тем не менее, возможно, все еще стоит придерживаться предварительного инкремента, потому что циклы выполняются много раз, и это означает, что вскоре может быть усилено небольшое снижение производительности.
В других языках, таких как С#, где оператор ++ не может быть перегружен, нет разницы в производительности. Операторы pre и post increment, используемые в цикле для продвижения переменной цикла, эквивалентны.
Коррекция: допускается перегрузка ++ в С#. Кажется, что, по сравнению с C++, в С# вы не можете перегружать версии pre и post независимо. Итак, я бы предположил, что если результат вызова ++ в С# не присваивается переменной или не используется как часть сложного выражения, тогда компилятор сократит до и после версий ++ до кода, который будет выполняться эквивалентно.
Ответ 3
В С# нет разницы при использовании в цикле for.
for (int i = 0; i < 10; i++) { Console.WriteLine(i); }
выводит то же самое, что и
for (int i = 0; i < 10; ++i) { Console.WriteLine(i); }
Как указывали другие, при использовании в целом я ++ и ++ у меня есть тонкая, но существенная разница:
int i = 0;
Console.WriteLine(i++); // Prints 0
int j = 0;
Console.WriteLine(++j); // Prints 1
i ++ читает значение i, затем увеличивает его.
++ я увеличивает значение i, затем читает его.
Ответ 4
Поскольку вы спрашиваете о различии в цикле, я думаю, вы имеете в виду
for(int i=0; i<10; i++)
...;
В этом случае у вас нет разницы в большинстве языков: цикл ведет себя одинаково независимо от того, пишете ли вы i++
и ++i
. В С++ вы можете написать свои собственные версии операторов ++, и вы можете определить для них отдельные значения, если i
имеет тип, определенный пользователем (например, ваш собственный класс).
Причина, почему это не имеет значения, состоит в том, что вы не используете значение i++
. Другое дело, когда вы делаете
for(int i=0, a = 0; i<10; a = i++)
...;
Теперь есть разница, потому что, как указывают другие, i++
означает приращение, но оценивает предыдущее значение, но ++i
означает приращение, но оценивается до i
(таким образом, он будет оценивать новый стоимость). В приведенном выше случае a
присваивается предыдущее значение i, а я - приращение.
Ответ 5
Возникает вопрос:
Есть ли разница в ++ я и я ++ в цикле for?
Ответ: Нет.
Почему каждый ответ должен содержать подробные объяснения о до и после приращения, когда об этом даже не спрашивают?
Этот цикл 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.
Ответ 6
Как показано в этом коде (см. разглашенный MSIL в комментариях), компилятор С# 3 не делает различий между я ++ и ++ я в цикле for. Если было принято значение я ++ или ++ 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++;
}
}
}
}
Ответ 7
Один (++ 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, полностью игнорирует сторону цикла. Нет фактической разницы для циклов, когда это "шаг" (для (...;...;)), но он может вступить в игру в других случаях.
Ответ 8
Вот пример 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."<init>":()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
}
Ответ 9
Нет разницы, если вы не используете значение после инкремента в цикле.
for (int i = 0; i < 4; ++i){
cout<<i;
}
for (int i = 0; i < 4; i++){
cout<<i;
}
Оба цикла будут печатать 0123.
Но разница возникает, когда вы используете значение после инкремента/уменьшения в вашем цикле, как показано ниже:
Pre Increment Loop:
for (int i = 0,k=0; i < 4; k=++i){
cout<<i<<" ";
cout<<k<<" ";
}
Вывод:
0 0
1 1
2 2
3 3
Поступающий цикл:
for (int i = 0, k=0; i < 4; k=i++){
cout<<i<<" ";
cout<<k<<" ";
}
Вывод:
0 0
1 0
2 1
3 2
Я надеюсь, что разница будет очевидна, если сравнить результат. Здесь указывается, что приращение/декремент всегда выполняется в конце цикла for, и, следовательно, результаты могут быть объяснены.
Ответ 10
Да, есть. Разница заключается в возвращаемом значении. Возвращаемое значение "++ 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.
Ответ 11
В обоих случаях нет никакой реальной разницы: "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
Ответ 12
В ++ и я ++ существует больше, чем циклов и различий в производительности. ++ я возвращает значение l, а я ++ возвращает 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, i.e., of the form const T&.
3- You cannot apply another post increment or decrement to the result of i++, i.e., 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;
}
Ответ 13
В javascript из-за следующего я ++ может быть лучше использовать:
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 в качестве отправной точки, вам нужно будет установить я в -1, чтобы заставить цикл работать с массивом при использовании ++ i.
При использовании я ++ следующее значение будет использовать увеличенное значение. Вы могли бы сказать, что я ++ - это способ подсчета людей, потому что вы можете начать с 0.
Ответ 14
Это пугает мой разум, почему люди могут писать выражение increment в for-loop как я ++.
В for-loop, когда третий компонент представляет собой простой оператор increment, как в
for (i=0; i<x; i++)
или
for (i=0; i<x; ++i)
нет никакой разницы в результирующих исполнениях.
Ответ 15
Как @Jon B говорит, что нет никакой разницы в цикле for.
Но в цикле while
или do...while
вы можете найти некоторые отличия, если вы делаете сравнение с ++i
или i++
while(i++ < 10) { ... } //compare then increment
while(++i < 10) { ... } //increment then compare
Ответ 16
Для петель может быть разница. Это практическое применение 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).
Ответ 17
Они оба увеличивают число. ++i
эквивалентно i = i + 1
.
i++
и ++i
очень похожи, но не совсем то же самое. Оба увеличивают число, но ++i
увеличивает число до того, как оценивается текущее выражение, а i++
увеличивает число после вычисления выражения.
int i = 3;
int a = i++; // a = 3, i = 4
int b = ++a; // b = 4, a =
Отметьте эту ссылку.
Ответ 18
Да, существует разница между ++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)
}
Ответ 19
Для i
пользовательских типов эти операторы могли (но не должны) иметь значимо различную семантику в контексте индекса цикла, и это могло (но не должно) повлиять на поведение описанного цикла.
Кроме того, в c++
, как правило, наиболее безопасно использовать форму предварительного приращения (++i
), поскольку ее легче оптимизировать. (Скотт Лэнгэм избил меня до этого лакомого кусочка. Проклятье, Скотт)
Ответ 20
Я не знаю других языков, но в Java ++ i является приращением префикса , что означает: увеличение i на 1, а затем используйте новое значение я в выражении, в котором находится i, а я ++ - приращение postfix, что означает следующее: используйте текущее значение 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);
}
и выход:
Ответ 21
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