循环中i ++和++ i之间的区别?

时间:2009-01-27 17:53:20

标签: post-increment pre-increment

++i循环中的i++for是否存在差异?它只是一种语法吗?

23 个答案:

答案 0 :(得分:214)

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

foreachwhile循环取决于您使用的增量类型。对于像下面这样的for循环,没有区别,因为你没有使用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++) { }

答案 1 :(得分:205)

预增量++ 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等),没有性能差异。但是,值得坚持使用预增量运算符作为指导,除非后增量运算符肯定是必需的。

这里有更多的讨论:
https://web.archive.org/web/20170405054235/http://en.allexperts.com/q/C-1040/Increment-operators.htm

在C ++中如果你正在使用STL,那么你可能正在使用带迭代器的for循环。这些主要有重写的++运算符,所以坚持预增量是一个好主意。编译器总是变得更聪明,而较新的编译器可能能够执行优化,这意味着没有性能差异 - 特别是如果增加的类型是在头文件中内联定义的(因为STL实现经常是这样),以便编译器可以看到该方法已实现,然后可以知道哪些优化可以安全执行。即便如此,它仍然值得坚持预增量,因为循环执行很多次,这意味着很小的性能损失很快就会被放大。


在C#等其他语言中,++运算符不能重载,没有性能差异。在循环中用于推进循环变量,前后增量运算符是等效的。

更正:允许在C#中重载++。看来,与C ++相比,在c#中你不能独立地重载前后版本。所以,我认为如果在C#中调用++的结果没有分配给变量或者作为复杂表达式的一部分使用,那么编译器会将++的前后版本缩减为等效执行的代码。

答案 2 :(得分:77)

在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的​​值然后读取它。

答案 3 :(得分:36)

问题是:

  

for循环中++ 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循环体内的代码执行后递增。

答案 4 :(得分:29)

既然你在循环中询问差异,我想你的意思是

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

在这种情况下,您在大多数语言中没有区别:无论您是写i++还是++i,循环的行为都相同。在C ++中,您可以编写自己的++运算符版本,如果i是用户定义的类型(例如,您自己的类),则可以为它们定义单独的含义。

之所以无关紧要,是因为您没有使用i++的值。另一件事是当你做

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

现在, 是一个区别,因为正如其他人指出的那样,i++表示增量,但计算为之前的值,但是{{1} }表示递增,但计算为++i (因此它将评估为新值)。在上面的情况中,i被赋予先前的i值,而i被递增。

答案 5 :(得分:15)

正如此代码所示(请参阅注释中的差异MSIL),C#3编译器在for循环中对i ++和++ i没有区别。如果正在使用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++;
            }
        }
    }
}

答案 6 :(得分:14)

一个(++ 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

编辑:Woops,完全忽略了循环方面的事情。当for循环是'step'部分(for(...; ...;))时,for循环没有实际的区别,但它可以在其他情况下发挥作用。

答案 7 :(得分:8)

这是一个Java样本和字节代码,后增量和前增量显示字节顺序没有区别:

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 PriOr PostIncrement):

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

}

答案 8 :(得分:6)

如果在循环中增加后没有使用该值,则没有区别。

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

两个循环都将打印0123。

但是当您在循环中使用增量/减量后的值时,差异就会出现:

预增量循环:

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循环结束时执行,因此可以解释结果。

答案 9 :(得分:5)

是的,有。差异在于返回值。 递增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. 

答案 10 :(得分:4)

两种情况都没有实际差异,“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

答案 11 :(得分: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, 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;
}

答案 12 :(得分:3)

令人难以置信的是,为什么人们会将for循环中的增量表达式写为i ++。

在for循环中,当第3个组件是简单的增量语句时,如

for (i=0; i<x; i++)  

for (i=0; i<x; ++i)   

所产生的执行没有区别。

答案 13 :(得分:3)

在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 。

使用 i ++ 时,以下值将使用增加的值。您可以说 i ++ 是人类计算的方式,因为您可以从 0 开始。

答案 14 :(得分:2)

正如@Jon B所说,for循环没有区别。

但是在whiledo...while循环中,如果您与++ii++

进行比较,您会发现一些差异
while(i++ < 10) { ... } //compare then increment

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

答案 15 :(得分:1)

他们都增加了数字。 ++i相当于i = i + 1

i++++i非常相似但不完全相同。两者都递增数字,但++i在计算当前表达式之前递增数字,而i++在计算表达式之后递增数字。

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

检查this link

答案 16 :(得分:1)

循环可能有所不同。这是后期/预增量的实际应用。

        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); - 循环迭代例如数组的所有元素(在这里免除foreach构造)。

答案 17 :(得分:1)

是的,++i循环中i++for之间存在差异,但在不寻常的用例中;当使用递增/递减运算符的循环变量在循环测试表达式中的for块中使用,或者使用其中一个循环变量时使用 。不,这不仅仅是语法上的事情。

代码中的i表示评估表达式i,运算符并不意味着评估,而只是一个操作;

  • ++i表示将i的增量值增加1,稍后评估i
  • i++表示评估i,然后将i的值增加1。

因此,从每两个表达式中获得的内容会有所不同,因为评估的内容各有不同。 --ii--

的所有内容都相同

例如;

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)
}

答案 18 :(得分:1)

  

了解 FOR 循环的作用

enter image description here

  

上图显示 FOR 可以转换为 WHILE ,因为它们最终具有完全相同的汇编代码(至少在gcc中)。因此,我们可以将 FOR 分解为几部分,以了解其功能。

for (i = 0; i < 5; ++i) {
  DoSomethingA();
  DoSomethingB();
}

等于 WHILE 版本

i = 0; //first argument (a statement) of for
while (i < 5 /*second argument (a condition) of for*/) {
  DoSomethingA();
  DoSomethingB();
  ++i; //third argument (another statement) of for
}

  

这意味着您可以使用 FOR 作为 WHILE 的简单版本:

     
      
  1. FOR (int i)的第一个参数在循环之前在外部执行。

  2.   
  3. FOR 的第三个参数(i ++或++ i)在循环的最后一行内部执行。

    < / li>   
     

TL:DR:无论i++还是++i,我们都知道,当它们独立运行时,它们本身没有区别,只有+1。

     

在学校里,他们通常教i ++方式,但是由于several reasons,很多人更喜欢++ i方式。

     

注意:过去,i ++对性能的影响很小,因为它不仅单独加1,而且将原始值保留在寄存器中。但是就目前而言,它没有什么区别,因为编译器使加号部分相同。

答案 19 :(得分:0)

在某些情况下 ++i 和 i+1 可能会给出不同的结果,同样适用于 --i、i - 1 等

这不是因为递增和递减运算符的工作方式存在缺陷,而是因为新程序员有时会忽略一个小事实。

根据经验,不要在数组的方括号内使用 inc/dec。例如,我不会用 arr[++i] 代替 arr[i + 1]。虽然两者都会让我们得到相同的 i 值,但我们在这里忽略了一些东西。

如果循环条件基于 i 的执行值,那么将 arr[i + 1] 替换为 arr[++i] 将导致错误。为什么?

假设 i = 5,那么 arr[i + 1] 将意味着 arr[6] 和 arr[++i] 虽然将意味着 arr[6] 但也会将 i 的值更改为 6 而这可能不会成为我们想做的事情。我们可能不想改变 i 的值,但由于一个简单的 ++/-- 运算符,我们改变了值。

所以在使用 ++/-- 运算符时要小心。

我希望,我能够使我的观点易于理解。

答案 20 :(得分:-2)

我不知道其他语言,但在Java ++ i 前缀增量,这意味着:将 i 增加1然后在 i 所在的表达式中使用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

答案 21 :(得分:-2)

对于i的用户定义类型,这些运算符可以(但不应该)在循环索引的上下文中具有有意义的不同语义,这可能(但应该not)影响所描述的循环的行为。

此外,在c++中,使用预增量形式(++i)通常最安全,因为它更容易优化。 (Scott Langham beat me to this tidbit。诅咒你,Scott)

答案 22 :(得分:-3)

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