引用类型变量回收 - 如果在其中声明,则是在循环中的每个循环中创建的新引用变量?

时间:2011-09-12 03:30:00

标签: c# oop

以下是:

MyObject myVariable;
for(int i = 0; i < objects.Length, i++){
  myVariable = objects[i];
  // do stuff...
}

效率更高:

for(int i = 0; i < objects.Length, i++){
  MyObject myVariable = objects[i];
  // do stuff...
}

因为每次都不会创建一个用于保存引用的新变量? (或者编译器足够智能,只是为了使用相同的变量)..

(如果创建了一个新变量,它是否在堆上进行了malloced?)

3 个答案:

答案 0 :(得分:62)

不,“变量”几乎完全是为程序员而存在的。您不是通过在方法中声明变量来在运行时创建任何其他工作。

理论上,当为该方法中声明的每个变量调用一个方法时,编译器将在堆栈上留出空间。因此,该方法中该变量的存在比其范围更重要。除非使用new关键字,否则堆上没有分配空间。

实际上,编译器可以识别具有如此短范围的变量,以便它们可以存储在CPU上的寄存器中,而不需要堆栈上的空间。例如:

var a = b[c];
a.ToString();
// never access "a" again.

......将与:

相同
b[c].ToString();

...因为编译器认识到它只需要存储b [c]的结果足够长时间来调用它上面的方法,所以它只能使用CPU寄存器而不是使用内存。

出于这个原因,在循环中声明变量 实际上可能导致该方法为变量分配 less 堆栈空间,具体取决于之后可能的逻辑流程。然而,这进入了巨大的微观优化,对大多数人来说没有任何意义。

更新

由于有些人似乎仍然认为在循环中声明变量会产生一些影响,我想我需要提供证据。在LINQPad中键入以下程序。

int j;
for(int i = 0; i < 5; i++)
{
    j = i;
}

......和......

for(int i = 0; i < 5; i++)
{
    int j = i;
}

执行代码,然后转到IL选项卡查看生成的IL代码。这两个程序都是一样的:

IL_0000:  ldc.i4.0    
IL_0001:  stloc.0     
IL_0002:  br.s        IL_0008
IL_0004:  ldloc.0     
IL_0005:  ldc.i4.1    
IL_0006:  add         
IL_0007:  stloc.0     
IL_0008:  ldloc.0     
IL_0009:  ldc.i4.5    
IL_000A:  blt.s       IL_0004

所以有无可辩驳的证据证明这在编译时没有任何区别。您将从两个程序中获得完全相同的编译IL。

答案 1 :(得分:1)

我对“问题”进行了基准测试,并同意StriplingWarrior。至少在速度上没有区别。

long start = Time();
long end = Time();
Console.WriteLine("Benchmark Runtime: " + (end - start) + " Microseconds");

for(int k = 0; k < 5; k++)
{
    start = Time();
    int j;
    for (int i = 0; i < 900000000; i++)
    {
        j = i;
    }
    end = Time();
    Console.WriteLine("Benchmark 1: " + (end - start) + " Microseconds");
}

for (int k = 0; k < 5; k++)
{
    start = Time();
    for (int i = 0; i < 900000000; i++)
    {
        int j = i;
    }
    end = Time();
    Console.WriteLine("Benchmark 2: " + (end - start) + " Microseconds");
}

结果:

Benchmark Runtime: 1 Microseconds
Benchmark 1: 1730816 Microseconds
Benchmark 1: 1725885 Microseconds
Benchmark 1: 1725629 Microseconds
Benchmark 1: 1726052 Microseconds
Benchmark 1: 1726121 Microseconds
Benchmark 2: 1725843 Microseconds
Benchmark 2: 1725576 Microseconds
Benchmark 2: 1726233 Microseconds
Benchmark 2: 1725786 Microseconds
Benchmark 2: 1729965 Microseconds

答案 2 :(得分:-5)

简短回答,是的。

答案很长,是的,它更快,但除非重复多次,否则几乎不可察觉。 : - )

我不确定编译器是否会对其进行优化,但我对此表示怀疑,如果确实如此,那么它还是有好处的,你应该把它写成好像它一样,让它成为习惯。