3

我想我理解堆栈和堆之间的主要区别。

在下面的程序中,在堆上创建了一个大小为 n 的对象。在堆栈上创建了一个指向这个 sofar 无名对象的指针 p,它占用 4 个字节(至少在我的系统上)。如果我理解得很好,因为引用不使用额外的内存,所以不会分配更多的内存(除了 main() 在堆栈上返回的 int 之外)。

Class Object;  // n bytes

int main() {
    Object* p = new Object();
    Object& r = *p;
    // ...
}

尽管如此,内存管理还不完全清楚:

1) 名称 p 和 r 存储在哪里?它们都是本地名称,所以我想它们也应该放在堆栈上?这不需要额外的内存来存储变量名和它所引用的内存部分之间的绑定吗?

2)指针的类型存储在哪里?指针在堆栈上仅占用 4 个字节,(我认为)这是存储内存地址的确切大小。计算机如何知道在该地址可以找到哪种类型?

3) 与 (2) 类似,堆上的 Object 需要 n 个字节的存储空间,并且对它的唯一(直接)引用需要 0 个字节。这个对象的类型存储在哪里,所以当使用r时,它知道它是哪种类型吗?

4)我知道编译后的程序也驻留在内存中的某个地方以指导它的执行。这是在堆栈还是堆上,还是这仍然是内存的另一部分?

4

3 回答 3

7

名称 p 和 r 存储在哪里?

它们不是 - 变量名称是静态的,并且在运行时不可用。编译器知道变量将存储在哪里,并生成代码以访问该内存位置,而无需任何名称。

它们可能在程序文件的特殊调试部分中可用,以允许调试器显示变量的值。

指针的类型存储在哪里?

它不是 - 类型也是静态的(除了与多态类类型相关的有限动态类型信息,但不是指针类型)。编译器知道类型,并生成代码以针对该类型以正确的方式访问存储的值。

这个对象的类型存储在哪里?

如果类型是多态的(即如果它是一个至少有一个虚函数的类类型),那么就会有一些静态数据,存储在一个你不能直接访问的未指定的地方,来描述这个类型。将有足够的数据来支持虚函数调用(通常是指向最终覆盖的指针表)和 RTTI(供 使用的继承结构的规范dynamic_cast,以及type_info通过 可用的结构typeid)。

否则,所有类型信息都是静态的。

[编译后的程序] 是在栈上还是在堆上,还是这仍然是内存的另一部分?

在典型的计算机上,它位于静态内存(代码文本部分)中,在程序启动时加载。在嵌入式系统上,它可能更永久地位于只读存储器中。

于 2014-11-26T09:35:18.817 回答
3

由于引用不使用额外内存,因此不会分配更多内存

C++ 标准中没有指定如何实现引用,但大多数编译器会像指针一样实现它们,因此在未优化的代码中,可能还有另外 4 个字节(在您的系统上)用于r...。

名称 p 和 r 存储在哪里

这是存储的指针的类型?

r[ ]的类型存储在哪里

它们在编译器运行时存在于编译器本身中,如果您使用例如 GCC 的选项,它们可能存在于放入生成的对象/库/程序中以帮助交互式调试的一些调试符号信息中g++ -g,但它们不能通过普通 C++ 程序语句存储或访问.

我知道编译后的程序也驻留在内存中的某个地方以指导它的执行。这是在堆栈还是堆上,还是这仍然是内存的另一部分?

编译后的程序是一堆二进制数据和机器码操作码(数字),操作系统知道如何加载并要求 CPU 解释和执行。该数据通常不在堆栈或堆上,而是在操作系统安排的“未初始化数据”、“初始化数据”和“代码”段/区域的混合中。

于 2014-11-26T09:35:45.587 回答
1

计算机永远不知道 p 和 r。变量名用于提高高级语言的可读性。例如,您可以通过以下方式获取汇编代码

gcc -S -c code.c

code.s 中根本没有 p 和 r

于 2014-11-26T09:41:49.720 回答