在用到循环的时候时常会出现这两代码。
第一种在 循环里面定义变量
如果
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 只被声明一次。
这两种代码中感觉上是第二种更好。但原因为是什么? 不明白。 不停的在 循环中声名变量有什么坏处?
不明白为什么这么多人人云亦云,为什么不自己看看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的位置不同。仅此而已。
第二种好哈,在循环外面定义变量只分配一次空间,循环结束后再回收
在循环内部定义变量,变量需要不断地分配分空,回收,再分配等,在引用型变量时表现得比较明显
当然,这只是我的理解哈,等高人高见!
第一种看起来不乱,避免在其他地方被调用而修改内容,而且在for循环结束时j就会被销毁,而第二种方法要等到整个方法结束时才被销毁,这样就节省了内存。另外,不管在哪里声明字段,第一次编译的时候都会先把所有的字段声明存放在程序的开头。
这个问题诡异,因为的代码是 int j=i+10;,如果是 j= j+i 呢,你怎么每次声明?
这压根是逻辑问题,和内存什么的无关
刚认真看了一下,功能不确定,没有可比性,并且值类型和引用类型效果是不一样的。
第二种好。
第一种情况是:变量会不断地被声明,分配空间,销毁空间。
第二种情况是:变量只声明一次,但是生命周期很长,只有在变量声明部分的“}”之后才会自动被释放。可以优化的是,在循环结束后,手动销毁这个变量。
但是第二种方法消耗的内存和CPU时间会少些。
你说的是C#的话,没有区别,会被编译优化
你说的是JS的话,恐怕在外部声明比较好
第二种方式更好!
第一种方式,变量 j 会循环声明 100 次,分配内存空间,然后再销毁,浪费资源。
第二种方式,变量 j 仅声明一次,循环结束后就会释放。
同一楼观点,不过对于现在的服务器来说,这点区别CPU还是可以承担的,并且还是C#写的。