26

我知道在 JavaScript 中,创建这样的 for 循环:for(int i = 0; i < arr.length; i++)成本很高,因为它每次都会计算数组长度。对于列表和数组,这种行为在 c# 中是否也很昂贵。还是在编译时进行了优化?还有其他语言,比如Java,是怎么处理的?

4

6 回答 6

37

在 C# 中它并不昂贵。一方面,没有“计算”:由于内联,查询长度基本上是一个基本操作。其次,因为(根据其开发人员的说法),编译器可以识别这种访问模式,并且实际上会优化任何(冗余)边界检查以访问数组元素。

顺便说一句,我相信现代 JavaScript 虚拟机也有类似的情况,如果还没有,很快就会出现,因为这是一个微不足道的优化。

于 2008-11-04T18:56:58.057 回答
10
  1. 所有 .Net 数组都有一个包含数组长度的字段,因此长度不是在使用时计算,而是在创建时计算。

  2. .Net 虚拟机非常擅长尽可能消除边界检查,这是其中边界检查移到循环之外的情况之一(在大多数情况下,如果不是,则只有 2 条指令开销)。

编辑:

数组边界检查消除

于 2008-11-04T18:59:51.920 回答
4

在几乎任何语言中,答案都是“视情况而定”。

大多数情况下,这取决于编译器是否足够聪明,能够判断您在循环中时列表或数组的长度是否会发生变化。

不过,这不太可能由语言规范定义。

因此,假设编译可能无法解决这个问题可能是安全的。如果您真的相信对象的长度不会改变,请随意计算长度并在循环控制结构中使用它。

但要注意其他线程...

于 2008-11-04T18:57:11.177 回答
1

我相信如果您使用 Linq Count() 扩展方法,那么它可能会在每次调用时进行计算。

于 2008-11-04T19:05:25.683 回答
0

如果它类似于 Java,它应该是 O(1) 操作。

我发现以下链接很有帮助: http: //www.devguru.com/Technologies/Ecmascript/Quickref/array.html

于 2008-11-04T18:58:46.540 回答
0

它还取决于该 getter 是在进行计算还是在访问已知值。

于 2008-11-04T18:59:23.230 回答