Каковы преимущества и недостатки подъема переменных в языках программирования?

Следующая программа 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++ предупредит вас в некоторых таких случаях.

На практике вы привыкнете к любой настройке.

Другие вопросы по тегам