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

mar*_*mnl 36 c# oop

以下是:

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

效率更高:

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

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

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

Str*_*ior 66

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

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

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

var a = b[c];
a.ToString();
// never access "a" again.
Run Code Online (Sandbox Code Playgroud)

......会是这样的:

b[c].ToString();
Run Code Online (Sandbox Code Playgroud)

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

出于这个原因,声明你变量内部环路可能实际上导致方法分配较少的变量堆栈空间,这取决于可能的逻辑流程之后.然而,这进入了巨大的微优化,对大多数人来说没有任何意义.

更新

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

int j;
for(int i = 0; i < 5; i++)
{
    j = i;
}
Run Code Online (Sandbox Code Playgroud)

......而且......

for(int i = 0; i < 5; i++)
{
    int j = i;
}
Run Code Online (Sandbox Code Playgroud)

执行代码,然后转到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
Run Code Online (Sandbox Code Playgroud)

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

  • 在循环内部声明也可以帮助优化器,因为它现在知道(1)变量不在循环外使用,(2)前一次迭代的值不需要转发到下一次迭代. (7认同)
  • @Raymond:无论声明局部变量的位置,优化器通常都可以知道所有这些. (3认同)
  • 在循环中声明也可以帮助*懒惰的其他开发人员阅读你的代码*因为*他/她*现在知道...... ;-) (2认同)