首页 新闻 会员 周边 捐助

这两种代码哪种更好?

0
[已解决问题] 解决于 2011-10-08 08:55

在用到循环的时候时常会出现这两代码。

第一种在 循环里面定义变量

如果

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 只被声明一次。

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

wunaigong的主页 wunaigong | 初学一级 | 园豆:4
提问于:2010-11-17 16:23
< >
分享
最佳答案
0

不明白为什么这么多人人云亦云,为什么不自己看看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的位置不同。仅此而已。

麒麟.NET | 老鸟四级 |园豆:3614 | 2010-12-02 14:40
其他回答(8)
0

第二种好哈,在循环外面定义变量只分配一次空间,循环结束后再回收

在循环内部定义变量,变量需要不断地分配分空,回收,再分配等,在引用型变量时表现得比较明显

当然,这只是我的理解哈,等高人高见!

artwl | 园豆:16736 (专家六级) | 2010-11-17 16:28
0

第一种看起来不乱,避免在其他地方被调用而修改内容,而且在for循环结束时j就会被销毁,而第二种方法要等到整个方法结束时才被销毁,这样就节省了内存。另外,不管在哪里声明字段,第一次编译的时候都会先把所有的字段声明存放在程序的开头。

贪心狸猫 | 园豆:872 (小虾三级) | 2010-11-17 16:34
同意一楼的观点,基本上已经回答了楼主的问题了
支持(0) 反对(0) 宪华 | 园豆:0 (初学一级) | 2010-11-17 16:39
@贪心狸猫:for循环结束j不会被销毁
支持(0) 反对(0) Ou lei | 园豆:619 (小虾三级) | 2010-11-17 18:01
当程序执行的时候不会在运算中间申请资源,只会通过地址调用资源,修改数据,所以第一次编译的时候就会把所有声明放在程序的最前,当一个字段最后使用的时候会默认插入语句表示回收内存,所以对高级语言来说声明放在哪里都一样,只是作用域不同。 下面有段代码可以看看: for (int i = 0, j = 0; i < 2;i++ ) { j=i+0; }
支持(0) 反对(0) 贪心狸猫 | 园豆:872 (小虾三级) | 2010-11-19 12:10
0

这个问题诡异,因为的代码是 int j=i+10;,如果是 j= j+i 呢,你怎么每次声明?

这压根是逻辑问题,和内存什么的无关

炭炭 | 园豆:190 (初学一级) | 2010-11-17 16:49
0

刚认真看了一下,功能不确定,没有可比性,并且值类型和引用类型效果是不一样的。

大河 | 园豆:215 (菜鸟二级) | 2010-11-17 16:50
0

第二种好。

第一种情况是:变量会不断地被声明,分配空间,销毁空间。

第二种情况是:变量只声明一次,但是生命周期很长,只有在变量声明部分的“}”之后才会自动被释放。可以优化的是,在循环结束后,手动销毁这个变量。

但是第二种方法消耗的内存和CPU时间会少些。

角逐魏蜀吴 | 园豆:533 (小虾三级) | 2010-11-17 16:52
0

你说的是C#的话,没有区别,会被编译优化

你说的是JS的话,恐怕在外部声明比较好

Gray Zhang | 园豆:17610 (专家六级) | 2010-11-17 18:01
0

第二种方式更好!

第一种方式,变量 j 会循环声明 100 次,分配内存空间,然后再销毁,浪费资源。

第二种方式,变量 j 仅声明一次,循环结束后就会释放。

/aiq浪子飞龙 | 园豆:1189 (小虾三级) | 2010-11-17 18:09
0

同一楼观点,不过对于现在的服务器来说,这点区别CPU还是可以承担的,并且还是C#写的。

费里曼 | 园豆:493 (菜鸟二级) | 2010-11-18 09:22
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册