在用到循环的时候时常会出现这两代码。 第一种在 循环里面定义变量 如果

for(int i=0;i<100;i++)
{
  int j=i+10;
      ..................
}

另外一种是

int j=0;
for(int i=0;i<100;i++)
{
   j=i+10;
      .........................
}

这两种代码中,第一种 j 是在循环中不停的被声明。 第二种方法中 j 只被声明一次。 这两种代码中感觉上是第二种更好。但原因为是什么? 不明白。 不停的在 循环中声名变量有什么坏处?

推荐图书

  • C++ Primer中文版(第4版)
  • More Effective C++:35个改善编程与设计的有效方法(中文版)
  • 设计模式:可复用面向对象软件的基础


1个回答

明白为什么这么多人人云亦云,为什么不自己看看IL呢?只有Gray Zhang指出了会被编译器优化,这才是正解(贪心狸猫说的也是正确的)。看C#代码:

static void DeclareInTheForLoop()
{
    for (int i = 0; i < 100; i++)
    {
        int j = i + 10;
    }
}

static void DeclareOutOfTheForLoop()
{
    int j = 0;
    for (int i = 0; i < 100; i++)
    {
        j = i + 10;
    }
}

再看IL代码:

.method private hidebysig static void  DeclareInTheForLoop() cil managed
{
  // 代码大小       26 (0x1a)
  .maxstack  2
  .locals init ([0] int32 i,
           [1] int32 j,
           [2] bool CS$4$0000)
  IL_0000:  nop
  IL_0001:  ldc.i4.0
  IL_0002:  stloc.0
  IL_0003:  br.s       IL_0010
  IL_0005:  nop
  IL_0006:  ldloc.0
  IL_0007:  ldc.i4.s   10
  IL_0009:  add
  IL_000a:  stloc.1
  IL_000b:  nop
  IL_000c:  ldloc.0
  IL_000d:  ldc.i4.1
  IL_000e:  add
  IL_000f:  stloc.0
  IL_0010:  ldloc.0
  IL_0011:  ldc.i4.s   100
  IL_0013:  clt
  IL_0015:  stloc.2
  IL_0016:  ldloc.2
  IL_0017:  brtrue.s   IL_0005
  IL_0019:  ret
} // end of method Program::DeclareInTheForLoop



.method private hidebysig static void  DeclareOutOfTheForLoop() cil managed
{
  // 代码大小       28 (0x1c)
  .maxstack  2
  .locals init ([0] int32 j,
           [1] int32 i,
           [2] bool CS$4$0000)
  IL_0000:  nop
  IL_0001:  ldc.i4.0
  IL_0002:  stloc.0
  IL_0003:  ldc.i4.0
  IL_0004:  stloc.1
  IL_0005:  br.s       IL_0012
  IL_0007:  nop
  IL_0008:  ldloc.1
  IL_0009:  ldc.i4.s   10
  IL_000b:  add
  IL_000c:  stloc.0
  IL_000d:  nop
  IL_000e:  ldloc.1
  IL_000f:  ldc.i4.1
  IL_0010:  add
  IL_0011:  stloc.1
  IL_0012:  ldloc.1
  IL_0013:  ldc.i4.s   100
  IL_0015:  clt
  IL_0017:  stloc.2
  IL_0018:  ldloc.2
  IL_0019:  brtrue.s   IL_0007
  IL_001b:  ret
} // end of method Program::DeclareOutOfTheForLoop

我看不出第一种方法多声明了什么变量,两种方法的唯一区别就是,由于第二种方法先声明了j,因此在调用栈中i和j的位置不同。仅此而已。