堆和栈
堆和栈
区别
项目 | 栈(Stack) | 堆(Heap) |
---|---|---|
存储位置 | 内存中的一块连续区域,由编译器自动分配与释放 | 内存中的一块较大空间,由程序员手动申请与释放(如 new / delete ) |
分配管理 | 编译器自动管理 | 程序员或运行库管理 |
生命周期 | 当函数结束时自动释放 | 直到显式释放或程序结束 |
存储内容 | 局部变量、函数参数、返回地址等 | 动态分配的对象或数组 |
存储响应 | 只要栈的剩余空间足够就能申请,否则提示栈溢出 | 系统从链表中找出一块空闲内存地址 |
申请速度和大小 | 系统自动分配,速度较快,内存连续大小一半不超过8M | 由new分配,速度比较慢,内存不连续容易产生内存碎片,但是大小只受限于计算机系统中有效的虚拟内存 |
工作原理
栈(Stack)
- 是一种先进后出(LIFO)的结构,或者说后进先出(FILO)
- 每进入一个函数,就会在栈上分配空间
- 函数返回后,该空间自动释放
1
2
3
void func() {
int a = 10; // 栈上分配
} // 函数结束,a自动销毁
堆(Heap)
- 通过动态分配(
new
,malloc
)得到 - 内存空间在使用后必须手动释放,否则会内存泄漏
1
2
3
4
void func() {
int *p = new int(10); // 堆上分配
delete p; // 手动释放
}
优缺点
方面 | 栈 | 堆 |
---|---|---|
速度 | 快(由CPU寄存器直接支持) | 慢(需要动态查找空闲块) |
空间大小 | 小(几MB) | 大(几百MB甚至GB) |
分配/释放 | 自动 | 手动(或智能指针管理) |
安全性 | 高(自动释放) | 低(可能内存泄漏或野指针) |
例子
1
2
3
4
5
6
7
8
9
void example() {
int a = 5; // 栈内存
int *p = new int(5); // 堆内存
std::cout << &a << std::endl; // 栈区地址,靠近高地址
std::cout << p << std::endl; // 堆区地址,靠近低地址
delete p; // 释放堆内存
}
通常情况下:
- 栈区从高地址向低地址增长
- 堆区从低地址向高地址增长
本文由作者按照 CC BY 4.0 进行授权