我一直想知道,在一般情况下,在循环之前声明一个丢弃的变量,而不是在循环内部重复,使任何(性能)差异? Java中的一个(非常无意义的)例子:

A)循环前声明:

double intermediateResult;
for(int i=0; i < 1000; i++){
    intermediateResult = i;
    System.out.println(intermediateResult);
}

B)声明(重复)内部循环:

for(int i=0; i < 1000; i++){
    double intermediateResult = i;
    System.out.println(intermediateResult);
}

哪个更好,a还是b?

我怀疑重复的变量声明(例b)在理论上会产生更多的开销,但编译器足够聪明,所以这无关紧要。例b的优点是更紧凑,并且将变量的作用域限制在使用它的地方。尽管如此,我还是倾向于根据示例a编写代码。

编辑:我对Java案例特别感兴趣。


当前回答

我一直认为,如果你在循环中声明变量,那么你就是在浪费内存。如果你有这样的东西:

for(;;) {
  Object o = new Object();
}

然后,不仅需要为每次迭代创建对象,还需要为每个对象分配一个新的引用。看起来,如果垃圾收集器很慢,那么就会有一堆需要清理的悬空引用。

然而,如果你有这样的情况:

Object o;
for(;;) {
  o = new Object();
}

然后,您只需创建一个引用,并每次为它分配一个新对象。当然,它可能需要更长的时间才能超出作用域,但这时只需要处理一个悬空引用。

其他回答

我认为这取决于编译器,很难给出一个一般的答案。

当我想在退出循环后查看变量的内容时,我使用(A)。它只与调试有关。当我希望代码更紧凑时,我使用(B),因为它节省了一行代码。

我用Node 4.0.0测试了JS,如果有人感兴趣的话。在循环外声明会导致~。平均超过1000次试验,每次试验1亿次循环,性能提高5毫秒。所以我要用最易读/可维护的方式来写,在我看来就是B。我本想把我的代码放在小提琴中,但我使用了现在性能的Node模块。代码如下:

var now = require("../node_modules/performance-now")

// declare vars inside loop
function varInside(){
    for(var i = 0; i < 100000000; i++){
        var temp = i;
        var temp2 = i + 1;
        var temp3 = i + 2;
    }
}

// declare vars outside loop
function varOutside(){
    var temp;
    var temp2;
    var temp3;
    for(var i = 0; i < 100000000; i++){
        temp = i
        temp2 = i + 1
        temp3 = i + 2
    }
}

// for computing average execution times
var insideAvg = 0;
var outsideAvg = 0;

// run varInside a million times and average execution times
for(var i = 0; i < 1000; i++){
    var start = now()
    varInside()
    var end = now()
    insideAvg = (insideAvg + (end-start)) / 2
}

// run varOutside a million times and average execution times
for(var i = 0; i < 1000; i++){
    var start = now()
    varOutside()
    var end = now()
    outsideAvg = (outsideAvg + (end-start)) / 2
}

console.log('declared inside loop', insideAvg)
console.log('declared outside loop', outsideAvg)

我把A和B的例子各运行了20次,循环了1亿次。(jvm - 1.5.0)

A:平均执行时间:0.074秒

B:平均执行时间:0.067秒

令我惊讶的是B稍微快一点。 尽管现在的计算机速度很快,但很难说你是否能准确地测量这一点。 我也会用A的方式来编码,但我想说这并不重要。

我一直认为,如果你在循环中声明变量,那么你就是在浪费内存。如果你有这样的东西:

for(;;) {
  Object o = new Object();
}

然后,不仅需要为每次迭代创建对象,还需要为每个对象分配一个新的引用。看起来,如果垃圾收集器很慢,那么就会有一堆需要清理的悬空引用。

然而,如果你有这样的情况:

Object o;
for(;;) {
  o = new Object();
}

然后,您只需创建一个引用,并每次为它分配一个新对象。当然,它可能需要更长的时间才能超出作用域,但这时只需要处理一个悬空引用。