引用类型变量回收 – 如果在其中声明,则是在循环中的每个循环中创建的新引用变量?
如下:
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
简短的回答,是的。
答案很长,是的,它更快,但除非重复多次,否则难以察觉。 🙂
我不确定编译器是否会对其进行优化,但我对此表示怀疑,如果确实如此,那么它仍然有效,你应该仍然把它写成它,就好像它没有,让它成为一个习惯。