堆、栈是两种数据结构。
栈是一种线性的数据结构,存储和访问数据时,都只能访问栈的一端。数据访问为 FILO(先进后出)。
堆是一种特殊的二叉树,(最大堆)具有以下两个性质:
在操作系统中,一般是指内存管理的栈区和堆区,栈区由系统自动控制,堆区是在程序中使用诸如 new/malloc
的指令进行调用的。
一个由 C/C++ 编译的程序占用的内存分为五个部分:栈区、堆区、全局区/静态区(存放全局变量或 static 静态变量)、常量区(宏或const类型)、代码区(函数体的二进制代码)。
有一个很好的例子:
int a = 0; // 全局初始化区
char *p1; // 全局未初始化区,两位在全局区的不同位置
int main () {
int b; // 栈
char s[] = "abc"; // 栈
char *p2; // 栈
char *p3 = "123456"; // 123456\0在常量区,p3在栈上。
static int c =0; // 全局(静态)初始化区
p1 = (char *)malloc(10); // 堆
p2 = (char *)malloc(20); // 堆
}
在 IOS 中(OC、Swift),堆、栈的使用与内存管理与 C 基本相同。其内存分配的示意图为:
在多线程的环境下,同一进程的线程有自己完全独立的栈,但共享堆区。
栈的空间由系统自动分配与回收,如正在运行的程序定义了一个变量 int a;
则系统自动在运行该程序的 进程/线程 的栈中开辟一个 int 整型变量的空间呈装变量 a。
栈是内存上一块较小的区域,其访问方式固定(只支持从顶部添加、移除数据),运行速度较快,且没有碎片。
堆分配 根据实际情况不同,有许多分配策略,但其性能始终是不及栈的。
栈一般用来存储函数参数、局部变量等数据。
在函数调用时,子函数的压栈顺序有其物理意义,而不仅仅是逻辑意义:
堆一般用来存储引用类型的对象数据。
个人总结,敬请指正。