5

在这三个来源之间,在效率方面是否存在差异?

for (int i=0; i<N; i++)
    int j = whatever();

int j;
for (int i=0; i<N; i++)
    j = whatever();

int i, j;
for (i=0; i<N; i++)
    j = whatever();

谢谢。

PS:显然我的问题不是关于变量的范围,而只是关于循环的效率,特别是在前两种情况下,变量 j 被声明为一次与 N 次。

4

9 回答 9

11

声明变量对性能没有影响。一旦代码被编译,JIT 就足够聪明,可以预先分配局部变量。

从技术上讲,限制变量的范围可以提高性能,因为它不必在不再需要变量后保留它,但我怀疑 JIT 足够聪明,也可以解决这个问题。

于 2013-07-18T16:17:45.263 回答
8

一旦编译器优化了代码,就应该没有区别。

如果您在默认关闭优化的调试模式下运行,如果您在循环范围内声明变量,则效率低于在循环范围外声明变量。

在这种情况下,对于循环的每次迭代,代码都会在堆栈上为变量创建空间,并在迭代后将其丢弃。这有点低效。

但是对于循环变量 (i),在 for 循环之前或内部声明它并不重要,因为它只会在堆栈上分配一次。

因此,在调试模式下得出结论,2 和 3 的性能都比 1 好。在发布模式下,所有 3 都相同。

于 2013-07-18T16:25:56.703 回答
4

声明变量会影响编译时间,而不是运行时间。局部变量在堆栈上占用的空间是在编译时分配的,因此运行时不会受到影响。

会受到影响的是可读性:通常,最好将变量声明在靠近它们使用的地方,并将它们保持在程序允许的范围内。从这个意义上说,您的第一个代码片段是最好的。

使用代码片段 2 或 3 的唯一原因是当您需要变量的值ij 循环完成之后,例如,找出break语句何时执行。从您的示例中无法判断是否是这种情况。

于 2013-07-18T16:17:38.270 回答
2

不。您需要了解代码被编译为字节码,然后在 Java 虚拟机 (JVM) 上运行,该虚拟机将字节码转换为机器码并即时进行优化 (JIT)。

许多简单的事情,例如多变量声明,在编译为字节码或 JIT 期间都被优化掉了。

我希望我可以将您链接到一篇关于此的好文章,但我没有想到。

于 2013-07-18T16:22:05.830 回答
1

它们实际上都是一样的。它们之间的唯一区别是,在您的第二个示例中,一个变量的范围在循环之外,而在第二个示例中,两个变量的范围都在循环之外。在您的第一个示例中,这两个变量都不能在循环之外访问,这通常是在循环中处理变量的更好方法,除非有理由在循环之外访问它们。

int x = 0;

只需 JVM 将原始 32 位值 0 分配给与x. 但是,当您在这种情况下使用自动装箱时,它会变得很有趣,因为它Integer x = 0需要 JVM 实例化一个具有更多资源需求的新对象。

于 2013-07-18T16:20:05.750 回答
0

在第一个示例中,变量将是初始化N时间。

基本上,这三个示例之间没有显着差异。取决于您是否需要j更广泛范围内的变量。这是主要的区别。

于 2013-07-18T16:17:12.070 回答
0

如所写?不。

有没有区别很重要的情况?是的。

这些情况是否经常出现,编译器无论如何都不会为您处理它?不。

在这两种情况下,最好的办法就是测试它。用“为什么运行速度比那个慢?”来回答(和帮助)要容易得多。

于 2013-07-18T16:17:55.840 回答
0

这三个示例在效率方面没有区别。但是根据编码标准,您应该在仅需要时声明变量。在变量的可见性方面也存在差异。让我解释

选项1

 for (int i=0; i<N; i++)
int j = whatever();

这里变量 j 的范围仅在 for 循环中

选项 2

int j;
for (int i=0; i<N; i++)
    j = whatever();

这里 j 在 for 循环的内部和外部可见,但 i 仅在 for 循环的范围内可见

选项 3

int i, j;
for (i=0; i<N; i++)
    j = whatever();

这里变量 i 和 j 在两个地方都是可见的,即 for 循环的外部和内部

于 2013-07-18T16:18:57.647 回答
0

除非您执行此代码片段数百万次,否则答案是选择最易读(因此也是最可维护)的源代码。

即使上述技术之一明显更快,您的大部分代码(超过 90%)也不会经常执行,因此它的速度与您的整体程序性能无关。专注于编写可读、可理解和可维护的代码。然后,您可以优化 10%(或更少)确实会导致性能瓶颈的代码。

于 2013-07-18T16:33:17.207 回答