【问题标题】:What are the benefits and drawbacks of variable hoisting in programming languages? [closed]编程语言中变量提升的优缺点是什么? [关闭]
【发布时间】:2020-11-29 21:11:46
【问题描述】:

以下 Python 程序 A 按预期输出 1,而以下 Python 程序 B 引发未绑定局部变量 x 错误,违反直觉。

  • 程序 A:
def f(): print(x)
x = 1
f()
  • 程序 B:
def f(): print(x); x = 2
x = 1
f()

Javascript 具有完全相同的行为。

  • 程序 A:
function f() { console.log(x); }
let x = 1;
f();
  • 程序 B:
function f() { console.log(x); let x = 2; }
let x = 1;
f();

但是,C++ 在这两种情况下都会按预期输出1

  • 程序 A:
#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; }

所以所有程序A输出1。一方面,Python 和 Javascript 与 C++ 之间的程序 B 的差异是由于它们不同的作用域规则:在 C++ 中,变量的作用域从它的声明开始,而在 Python 和 Javascript 中,它从声明变量的块的开头开始。因此,在 C++ 中,函数 f 中的打印变量 x 解析为全局变量 x 的值 1,因为它是执行时上下文中唯一的变量。在 Python 和 Javascript 中,函数 f 中的打印变量 x 解析为空并引发未绑定的局部变量 x 错误,因为局部变量 x 在执行时已经在上下文中,因此它掩盖了全局变量 @987654341 @ 尚未绑定到值 2。 Python 和 Javascript 的这种违反直觉的行为也称为变量提升,因为它在块的开头“提升”变量声明(但不是定义)。

编程语言中变量提升的优缺点是什么?

【问题讨论】:

  • 违反直觉的行为”是由于块/函数范围。在内部,当解析嵌套作用域中的变量时,可以更快地从其作用域的顶部找到声明。最初在 JS 中(解释为 var 和函数范围),您可以运行“愚蠢”的代码而不会中断执行。缺点是难以调试的逻辑错误。
  • @Teemu 是的var 不会像let 那样中断执行,因为它将值undefined 分配给局部变量x 而不是什么都没有,而是局部变量x 的范围保持不变,因为它仍然像 let 一样屏蔽全局变量 x
  • 是的,这是提升的结果。在let(和const)的上下文中,使用了术语temporal dead-zone
  • Guido van Rossum(Python 的创造者)自己回答了here

标签: javascript python c++ scope hoisting


【解决方案1】:

这更像是语言的产物,而不是面向程序员的特性。

对于 python 和 javascript,新变量意味着在名称字典中分配一个条目,直到您实际创建一个对象并分配它。在 C++ 中,运行时没有名称字典,定义需要实际为对象分配内存(据我们所知,它可能是一个 10MB 的数组)。

如果您确实需要,这确实允许 C++ 适应更小的内存占用。否则没有太多考虑的理由。

从开发人员的角度来看,您有一个错误。您的x 有 2 个含义。编程已经够难了,因为它没有变量改变对你的意义,所以我会尽可能避免。我认为 C++ 在某些情况下会给你一个警告。

实际上,您会习惯于任何一种设置。

【讨论】:

  • 有趣。那么您是说变量提升是一个理想的编程功能,因为它可以防止名称绑定到同一块中的非本地实体和本地实体?不,Clang 和 GCC 都没有对 C++ 程序发出警告。
  • @Maggyero 我希望有一个明确的警告或错误来告诉你这种情况正在发生。您在提升示例中遇到的错误可能会被误解和解决。
  • 我在 Python 官方论坛上问了关于变量提升的动机的问题,最后 Guido 自己给出了理由。有兴趣可以发帖here
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-23
  • 2011-03-24
  • 2011-03-14
  • 1970-01-01
  • 1970-01-01
  • 2014-06-26
相关资源
最近更新 更多