静态(static)存储 vs 堆(heap) vs 栈(stack)
本文译自:Static Storage vs Heap vs Stack
以下是编译器存储分配的总结。
1 静态(static)与动态
-
静态(static):编译器可以只查看程序的文本来进行存储。静态(static)分配尽可能多的数据对象的原因之一是这些对象的地址可以编译成目标代码。
-
动态:可以通过查看程序在运行时做了什么来进行存储。
2 静态(static)
编译器生成的全局常量和其他数据(例如支持垃圾收集的信息)被分配为静态(static)存储。静态(static)变量在执行开始之前绑定到内存单元,并在整个执行过程中保持绑定到同一内存单元。例如,C 静态(static)变量。
-
优势:效率(直接寻址)、历史敏感子程序支持
-
缺点:缺乏灵活性,如果这是唯一类型的变量,则没有递归,就像 Fortran 中的情况一样
3 堆(heap)
可能比对创建它的过程的调用更有效的数据通常分配在堆(heap)上。例如,new 用于创建可以从一个过程传递到另一个过程的对象。
堆(heap)的大小无法在编译时确定。仅通过指针或引用引用,例如C++中的动态对象,Java中的所有对象。
Java中,是一个可动态申请的内存空间(其记录空闲内存空间的链表由操作系统维护),在java中,所有使用 new Xxx()
构造出来的对象都在堆中存储一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。
-
优点:提供动态存储管理
-
缺点:低效且不可靠
4 栈(stack)
过程的局部名称在栈(stack)上分配空间。栈(stack)的大小无法在编译时确定。
Java中,由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
- 优点:
- 允许递归
- 节省存储空间
- 缺点:
- 分配和释放的开销
- 子程序不能对历史敏感
- 低效引用(间接寻址)