【问题标题】:Are scopes stored in a stack?范围是否存储在堆栈中?
【发布时间】:2018-04-21 00:44:33
【问题描述】:

我遇到了这种说法(source)

意味着将函数调用和作用域放在堆栈中

但是如何/为什么要存储作用域?

【问题讨论】:

  • 与其说是“将范围存储在堆栈中”,不如说是事物存储在堆栈中,从而为它们提供了范围。如果这没有立即意义,请阅读堆分配和堆栈分配之间的区别。
  • 范围只是一个术语,表示最近的东西(函数调用、变量、参数)被推入堆栈,堆栈是 RAM 的一部分。
  • 并不是将作用域存储在堆栈中; 编译器会这样做,以跟踪什么在哪里。当代码开始一个块时,编译器为变量名创建一个新记录并将其压入堆栈;当变量被定义时,它们的名字进入最近的记录。当代码离开一个块时,它将最后一条记录从堆栈中弹出并丢弃。这将删除该块中定义的所有名称。

标签: c++ scope stack


【解决方案1】:

这句话可以更好地表达。你需要先做一些观察。

  1. 作用域是一种语义构造。它定义了您可以在何处使用名称(用于变量、类型、函数等)。以及这个名字的含义。

  2. 有不同类型的作用域。不少只是编译时的事情。例如,命名空间和类也定义了一个范围。

  3. 函数也定义范围,但函数“运行”。因此,它们的上下文必须具有某种运行时表示。

  4. 递归需要调用相同的函数,但每次重入调用的函数上下文必须不同。

最后一点是为什么经常使用“调用堆栈”来实现函数调用。每个堆栈记录都与正在运行的函数的上下文相关。因此,函数范围内的名称将引用调用堆栈上的项目。

【讨论】:

  • 谢谢!但是既然示波器是可以存储的东西,它们一定是内存中的物理东西,对吧?那么作用域真的像对象一样存储在内存中吗?此外,我从不同来源(例如 cppreference)阅读了很多关于范围的信息,但我从未遇到过关于范围存储在某处的声明,这是为什么呢?这是否也包含在标准中的某个地方(我必须搜索它)?谢谢!
  • @sdsadasdasd - 不存储范围。它们是一个语义概念。存储了一个函数上下文,函数的范围定义了该上下文中的内容。但是范围是没有存储的。
  • 嗯好吧,但是如果函数的上下文存储在内存中的某个位置,如果不直接存储作用域,我仍然不知道每个实体与其作用域的关联程度如何?它是在符号表中完成的,还是函数的上下文存储在内存中的某个地方,这个地方专门用于某个范围?虽然你让我明白了很多,但我仍然有一些奇迹:)
  • @sdsadasdasd - 这取决于实现,纯语言不涉及这一点。将 C++ 语言定义的概念转换为生成代码的运行时属性的东西决定了如何。一种流行的实现是使用“堆栈指针”。这指向调用堆栈的顶部。该函数的代码知道变量位于sp + 2sp+4。这完全取决于 ABI。
  • 好的,谢谢。你能找到它在 C++ 标准中的位置吗,因为我找不到?另外,在这种情况下,“ABI 依赖”到底是什么意思?
【解决方案2】:

答案不是 C++ 特定的。 C++ 在运行之前使用编译模型(至少在概念上,实现可能不同)。在 C++ 模型中,作用域是在编译时解析的。编译器很可能为此使用某种堆栈数据结构。

在运行时,有一个函数调用栈,它通常保存函数返回地址和每个活动函数的局部变量,但在 C++ 中,这个运行时栈不需要保存作用域。

【讨论】:

  • 这个数据结构可以是符号表吗?
  • @sdsadasdasd:这是一个很好的开始假设。如果你想编写一个真正的编译器,其他的事情就会发挥作用——真正的符号表不是一个单一的数据结构。
  • 但是我仍然没有得到一些东西:实体连接到特定范围的内存如何?是通过区分堆栈还是如果是,这个堆栈如何与某个类、函数或其他东西相关联?
  • @sdsadasdasd:这并没有真正的意义(并且向我暗示你仍然没有在编译器和运行时环境之间做出严格的区分)。就拿第二个词来说,你想参考哪个记忆?
  • 嗯...用于存储对象等的内存(不确定是否具有特定名称)。假设一个对象的地址为 0x00020,这个地址是否是连接到某个范围的内存中某个位置内的某个地址?就像地址 0x00010-0x00050 可能专用于某个范围一样,它是这样工作的吗?还是只是某个函数的堆栈与某个范围相连?也许这是一个有点糟糕的措辞.. :/
猜你喜欢
  • 2012-04-17
  • 1970-01-01
  • 2021-01-25
  • 2016-10-11
  • 2014-10-16
  • 2013-12-06
  • 2012-12-13
  • 2015-04-18
相关资源
最近更新 更多