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

如下:

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

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

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

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

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

……会是这样的:

 b[c].ToString(); 

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

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

更新

由于有些人似乎仍然认为在循环中声明变量有一些影响,我想我需要提供证据。 在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 

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

我做了Benchmark的“问题”,并同意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 

简短的回答,是的。

答案很长,是的,它更快,但除非重复多次,否则难以察觉。 🙂

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