2014-01-13 3 views
4

У меня есть очень простой вопрос о правилах определения области видимости. Когда вы объявляете переменную внутри цикла, скажем:Объявление переменных в цикле

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

Является ли новая int переменная, объявленная в каждой итерации цикла? Или это то, что a уничтожен в конце каждой итерации и вновь создан снова? Как компилятор в Java или C++ понимает и реализует это?

+3

В чем разница? –

+0

Обратите внимание, что это не вопрос ООП; речь идет о правилах охвата, которые характерны для разных языков. FWIW, переменная 'int', как в этом случае, обычно будет просто назначаться реестром компилятором. – chrylis

+1

Когда вы задаете хороший вопрос, вам не нужно беспокоиться о downvotes. –

ответ

3

Вы должны различать логический уровень и уровень реализации.

С логической точки зрения переменная на самом деле не «создана» или «разрушена», но так вы могли бы ее себе представить. Переменная - это просто , объявленная в пределах scope, поэтому она будет существовать (вы можете назначить ей и прочитать ее значение), она инициализируется в начале блока (поэтому она имеет значение 0), и это не " t видно вне кодового блока. Вот что говорит определение языка. В C++, если вы опускаете инициализацию (т. Е. Часть =0), язык не делает никаких предположений о том, что такое значение (поэтому компилятор может «повторно использовать» ячейку памяти). В Java, тем не менее, инициализация неявна, поэтому a также будет установлен на ноль, если вы опустите инициализацию.

На уровне реализации компилятор более или менее свободен делать все, что захочет, до тех пор, пока он выполняет вышеуказанные спецификации. Поэтому на практике это, скорее всего, зарезервирует некоторое пространство в стеке и использует эту же память для каждой итерации, чтобы сохранить значение a. Поскольку вы использовали инициализатор, значение 0 будет записано в это место в начале каждого цикла. Обратите внимание, что если a не используется в пределах области действия, компилятор также может просто оптимизировать его. Или, если возможно, он может назначить его регистру CPU.

Однако теоретически компилятор также может зарезервировать «новую» ячейку памяти для a на каждой итерации и очистить все из них в конце цикла (хотя это может привести к StackOverflow (!) Для длинных циклов. .).Или используйте распределение динамической памяти, собранное с помощью мусора (что приведет к низкой производительности ...).

+0

Большое спасибо за подробный и информативный ответ :) – SoulRayder

+2

Имейте в виду, если вы это сделаете: 'X a (0);' где X - класс, конструктор будет вызываться в начале каждой итерации, а деструктор на конец каждой итерации. Если компилятор не может определить, что «вызов конструктора и деструктора ничего не делает». –

1

Это указано только в исходном коде. В байт-коде просто использует локальную переменную в стеке, которая будет инициализирована с 0 на каждой итерации. Разница с объявлением вне цикла заключается в том, что когда он находится внутри цикла, JVM будет повторно использовать переменную, занятую a.

2

Мне было легче думать о a как о той же переменной, которая неоднократно создавалась и уничтожалась.

+2

@EvgeniyDorofeev: Я не против других людей, редактирующих мои ответы, но всегда приятно получить комментарий, объясняющий причины крупных изменений, подобных этому. – NPE

+0

Это было по ошибке, но я исправил его, не так ли? –

1

a создавать и уничтожать после каждой итерации.

2

В основном, является локальной переменной, которая инициализируется каждой итерации в цикле со значением 0, а затем уничтожены, и так далее, до тех пор пока цикл не будет завершен, когда он в конечном счете разрушен

Примечание:

while(//Some Condition) 

бы закомментировать правую скобку, и поэтому код не будет работать в любом случае

правильно это:

while(/* some condition */) 
Смежные вопросы