Каковы преимущества и недостатки подъема переменных в языках программирования?
Следующая программа Python A выводит 1
, как и ожидалось, в то время как следующая программа Python B вызывает несвязанную локальную переменную x
ошибка, как ни странно.
- Программа А:
def f(): print(x)
x = 1
f()
- Программа B:
def f(): print(x); x = 2
x = 1
f()
Javascript ведет себя точно так же.
- Программа А:
function f() { console.log(x); }
let x = 1;
f();
- Программа B:
function f() { console.log(x); let x = 2; }
let x = 1;
f();
Однако C++ выводит 1
в обоих случаях, как и ожидалось.
- Программа А:
#include <iostream>
int x;
void f() { std::cout << x; }
int main() { x = 1; f(); return 0; }
- Программа B:
#include <iostream>
int x;
void f() { std::cout << x; int x = 2; }
int main() { x = 1; f(); return 0; }
Так что все программы выходят 1
. Различия в программах B между Python и Javascript, с одной стороны, и C++, с другой, обусловлены их разными правилами области видимости: в C++ область видимости переменной начинается с ее объявления, а в Python и Javascript - с начало блока, где объявлено переменный. Следовательно, в переменной печати C++x
в функции f
разрешается к значению 1
глобальной переменной x
поскольку на данном этапе выполнения это единственная переменная в контексте. В переменной печати Python и Javascriptx
в функции f
ничего не разрешает и вызывает несвязанную локальную переменную x
ошибка, поскольку локальная переменная x
уже находится в контексте в этой точке выполнения и поэтому маскирует глобальную переменную x
еще не будучи привязанным к ценности 2
. Это противоречивое поведение Python и Javascript также известно как подъем переменных, поскольку оно "поднимает" объявления переменных (но не определения) в начале их блоков.
Каковы преимущества и недостатки подъема переменных в языках программирования?
1 ответ
Это скорее артефакт языка, чем функция, ориентированная на программистов.
Для python и javascript новая переменная означает выделение записи в словаре имен до тех пор, пока вы не создадите объект и не назначите его. В C++ нет словаря имен во время выполнения, определение должно фактически выделять память для объекта (и это может быть массив размером 10 МБ, насколько нам известно).
Это позволяет C++ занимать меньший объем памяти, если вам это действительно нужно. В противном случае нет особых причин об этом думать.
С точки зрения разработчика у вас есть ошибка. Твойx
имеет 2 значения. Программирование достаточно сложно и без того, чтобы переменные меняли значение для вас, поэтому я бы по возможности избегал. Я думаю, что C++ предупредит вас в некоторых таких случаях.
На практике вы привыкнете к любой настройке.