直接访问数组元素与将其分配给变量

时间:2011-08-19 22:57:54

标签: language-agnostic performance

在性能方面,最好是“直接”多次访问数组元素,还是将其值赋给变量并使用该变量?假设我将在以下代码中多次引用该值。

这个问题背后的原因是,访问数组元素可能每次完成时都需要一些计算成本,而不需要额外的空间。另一方面,将值存储在变量中会消除此访问成本,但会占用额外的空间。

// use a variable to store the value
Temp = ArrayOfValues(0)
If Temp > 100 Or Temp < 50 Then
    Dim Blah = Temp
    ...

// reference the array element 'directly'
If ArrayOfValues(0) > 100 Or ArrayOfValues(0) < 50 Then
    Dim Blah = ArrayOfValues(0)
    ...

我知道这是一个微不足道的例子,但假设我们在谈论实际使用中的更大规模(其值将被多次引用),在什么时候需要考虑空间和计算时间之间的权衡(如果在全部)?

2 个答案:

答案 0 :(得分:3)

这是标记语言不可知的,但我真的不相信它。这篇文章回答了问题的C和C ++版本。

优化编译器可以处理“裸”数组访问;在C或C ++中,没有理由认为如果没有在其间调用函数,编译器就不会记住内存位置的值。 E.g。

int a = myarray[19];
int b = myarray[19] * 5;
int c = myarray[19] / 2;
int d = myarray[19] + 3;

但是,如果myarray不只是定义为int []但实际上是“花哨的”,特别是某个用户定义的容器类型,其函数operator[]()在另一个翻译单元中定义,那么该函数必须每次请求值时调用(因为函数在内存中的位置返回数据,而本地函数不知道函数的结果是否为常量)。

即使使用'裸'数组,如果你在函数调用周围多次访问同一个东西,编译器同样必须假设值已被更改(即使它可以记住地址本身)。 E.g。

int a = myarray[19];
NiftyFunction();
int b = myarray[19] * 8;

编译器无法知道myarray [19]在函数调用之前和之后将具有相同的值。

所以 - 一般来说,如果你知道一个值在本地范围内是不变的,那么将它“缓存”在一个局部变量中。您可以进行防御性编程并使用断言来验证您放置的东西:

int a = myarray[19];
NiftyFunction();
assert(myarray[19] == a);
int b = a * 8;

最后一个好处是,如果调试器中的值没有隐藏在某个数组中,则更容易检查它们。

答案 1 :(得分:2)

内存消耗的开销非常有限,因为对于引用类型,它只是一个指针(几个字节),大多数值类型也只需要几个字节。

在大多数语言中,数组是非常有效的结构。获取索引不涉及任何查找,只是一些数学(每个数组槽需要4个字节,因此第11个槽位于偏移40处)。然后,边界检查可能有一些开销。为新的本地var分配内存并释放它也需要一些cpu周期。所以最后它还取决于你通过复制到本地var来消除多少个数组查找。

事实上,你真的需要非常糟糕的硬件,或者真的有很大的循环,这对于它来说非常重要,如果对它进行了不错的测试。我个人经常选择单独的变量,因为我发现它使代码更易读。

你的例子很奇怪,因为你在创建本地var之前做了2次数组查找:) 这更有意义(消除2次查找)

Dim blah = ArrayOfValues(0)
if blah > 100 or blah < 50 then
...