我一直想知道,在一般情况下,在循环之前声明一个丢弃的变量,而不是在循环内部重复,使任何(性能)差异? 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案例特别感兴趣。


当前回答

作为一般规则,我将变量声明在最内部的可能范围内。如果你不在循环外使用intermediateResult,那么我会用B。

其他回答

我怀疑一些编译器可以将两者优化为相同的代码,但肯定不是全部。所以我觉得你还是选择前者比较好。使用后者的唯一原因是希望确保声明的变量仅在循环中使用。

哪个更好,a还是b?

从性能的角度来看,你必须衡量它。(在我看来,如果你能测量到差异,编译器不是很好)。

从维护的角度来看,b更好。在同一个地方声明和初始化变量,在尽可能窄的范围内。不要在声明和初始化之间留下空隙,不要污染不需要的名称空间。

这取决于语言和确切的用法。例如,在c# 1中,这没有什么区别。在c# 2中,如果局部变量是通过匿名方法(或c# 3中的lambda表达式)捕获的,则会产生非常显著的差异。

例子:

using System;
using System.Collections.Generic;

class Test
{
    static void Main()
    {
        List<Action> actions = new List<Action>();

        int outer;
        for (int i=0; i < 10; i++)
        {
            outer = i;
            int inner = i;
            actions.Add(() => Console.WriteLine("Inner={0}, Outer={1}", inner, outer));
        }

        foreach (Action action in actions)
        {
            action();
        }
    }
}

输出:

Inner=0, Outer=9
Inner=1, Outer=9
Inner=2, Outer=9
Inner=3, Outer=9
Inner=4, Outer=9
Inner=5, Outer=9
Inner=6, Outer=9
Inner=7, Outer=9
Inner=8, Outer=9
Inner=9, Outer=9

不同之处在于,所有的操作都捕获相同的外部变量,但每个操作都有自己独立的内部变量。

我的做法如下:

如果变量类型为simple (int, double,…)我更喜欢变种b(里面的)。 原因:减少变量的范围。 如果变量的类型不简单(某种类或结构),我更喜欢变量a(外部)。 原因:减少与医生的通话次数。

A)比B).........更安全想象一下,如果你在循环中初始化结构而不是'int'或'float'然后呢?

就像

typedef struct loop_example{

JXTZ hi; // where JXTZ could be another type...say closed source lib 
         // you include in Makefile

}loop_example_struct;

//then....

int j = 0; // declare here or face c99 error if in loop - depends on compiler setting

for ( ;j++; )
{
   loop_example loop_object; // guess the result in memory heap?
}

您肯定会遇到内存泄漏的问题!因此,我认为“A”是更安全的赌注,而“B”是容易受到内存积累的影响,特别是工作在近源库中。你可以在Linux上使用“Valgrind”工具检查,特别是子工具“Helgrind”。