循环内部的变量声明

4

我有一个关于作用域规则的非常基本的问题。当你在循环内部声明一个变量时,比如说:

while ( /*some condition*/ )
{
  int a = 0;
  //Remaining operations
}

在循环的每次迭代中,是否会声明一个新的int变量?还是说a在每次迭代结束时被销毁并重新创建?Java或C++编译器如何理解和实现这个过程?


3
区别会是什么? - Dawood ibn Kareem
请注意,这不是一个面向对象编程的问题;它涉及到作用域规则,这是针对不同语言的具体规定。顺便说一下,在这种情况下,一个 int 变量通常会被编译器分配到一个寄存器中。 - chrylis -cautiouslyoptimistic-
1
当你提出一个好问题时,你不需要担心会被踩。 - Ruchira Gayan Ranaweera
我认为这取决于编译器。 - Maroun
@david:我只是想了解面向对象编程中这种代码的内部工作原理,因为它是OOPS独有的。 - SoulRayder
显示剩余3条评论
5个回答

3
你需要区分逻辑层和实现层。
从逻辑角度来看,变量并没有真正的“创建”或“销毁”,但你可以这样想。变量只是在某个作用域内被声明,因此它保证存在(可以对其进行赋值和读取其值),在块的开头初始化(因此它的值为0),并且在代码块之外不可见。这就是语言定义的内容。在C++中,如果省略了初始化(即省略了“= 0”部分),语言不会对值做出任何假设(因此编译器可以自由地“重用”内存位置)。在Java中,如果省略了初始化,则初始化是隐式的,因此如果省略了初始化,“a”也将被设置为零。
在实现层面上,只要满足以上规范,编译器基本上可以自由地执行任何操作。因此,在实践中,它很可能会在堆栈上保留一些空间,并在每次迭代时使用相同的内存来存储“a”的值。由于您使用了一个初始化程序,每个循环开始时都会将值“0”写入此位置。请注意,如果在作用域内未使用“a”,编译器也可以简单地优化掉它。或者,如果可能的话,可以将其分配给CPU寄存器。
然而,从理论上讲,编译器也可以在每次迭代中为“a”保留一个“新”的内存位置,并在循环结束时清除所有内存位置(尽管这可能会导致堆栈溢出!)。或使用垃圾收集的动态内存分配(这将导致性能不佳...)。

2
请注意,如果您执行以下操作:X a(0); 其中 X 是一个类,则构造函数将在每次迭代开始时被调用,并且析构函数将在每次迭代结束时被调用。除非编译器可以确定“调用构造函数和析构函数不会做任何事情”。 - Mats Petersson

2
基本上,a是一个本地变量,在循环中每次都会被初始化为值0,然后被销毁,以此类推,直到循环结束时被最终销毁。
注意:
 while(//Some Condition) 

会注释掉右括号,因此代码无法运行

请将其更正为:

会注释掉右括号,因此代码无法运行。

while(/* some condition */)

2

我认为将 a 视为一个被反复创建和销毁的相同变量更容易理解。


2
@EvgeniyDorofeev:我不介意其他人编辑我的答案,但是得到一个解释这样的重大修改背后原因的评论总是很好的。 - NPE
那是我的失误,但我已经修复了,不是吗? - Evgeniy Dorofeev

1

这个变量只在源代码中声明,字节码中它只是使用了栈上的一个局部变量,该变量每次迭代都会被初始化为0。与循环外声明的区别在于,当它在循环内部时,JVM将重用变量a占用的位置。


1
在每次迭代后,a都会被创建并销毁。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接