首页 > 代码库 > 堆与栈

堆与栈

堆栈,堆栈,从一开始编程课的时候,老师就和我们在说,好的东西都放在栈里,垃圾的东西放在堆里,我一直不能完全理解,直到后来做了一些嵌入式的项目和上了一些课,有了一些自己的理解。

堆栈:分为堆和栈。

数据结构的角度来说:堆和栈分别属于不同的数据结构,栈是一种特殊的线性结构,可以认为它是一种特殊的线性表,但是添加和删除的方式比较特别,这个线性表只能从尾部添加(俗称入栈),也必须从尾部删除(出栈或弹栈),也就是所谓的先进后出。这个作用后面再说。而堆就不同了,堆是一种特殊的二叉树,、是一个深度为h的树,且满足下列条件:1.从根到h-1层是一个完全二叉树;2.任意节点都小于它的后裔,最小元在堆的根上(维基百科)。

从数据结构上说,这两种就是不一样了,栈是线性结构,而堆是树形结构

但是我们在实际的操作时候,是对内存进行操作,所以从内存的角度,堆栈又和上面定义的有所不同。

从嵌入式c语言编程的角度,一般程序都放在flash中,而实际运行的时候,都是在RAM中进行操作,所以一开始就需要在内存中分配空间,在一开始分配空间时候,先分配一些空间用于存储全局变量,并分配一个栈的空间,这个栈的大小取决于内存的大小和分配策略。而堆就相当于后面内存中:除了常量区,代码区,栈等之后的空闲区域。

下面一段代码,可以比较简单的看出来平时我们写的变量一般写在哪里:

#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
	int a = 0;  //a在栈里
	char b = ' ';//b在栈里
	static int c =0;//c在静态区
	char *p1 = (char *)malloc(10); free(p1)//p1在堆上 
	return 0;
}

所以栈(stack)和堆(heap)在内存上有以下不同:

第一点是分配空间上的不同,栈是系统分配空间,只要栈还有空间,系统就会分配,但是堆都是像内存中自动申请;

第二点就是释放空间的不同,栈是系统自动释放,而堆里的东西需要程序员手动释放,如果不释放,会一直占用内存空间。但是栈的分配空间小很多,如果写一句,char a[10000]; 一般debug的时候都会报错——栈溢出。而堆一般不会出现这种情况,因为堆是内存中空闲的空间,一般系统会以链表的形式记录下内存中空闲的空间,所以不需要太在意内存空间不够;

第三点是效率,可以分为访问效率和存储效率,在访问效率方面:栈由系统分配,速度快,而堆访问速度慢;在存储方面,由于这涉及到内存与cache映射,堆一般是在二级cache中,栈一般用的是一级cache,硬件上的存储速度就不一样,然后是程序实际执行逻辑,堆用malloc,需要寻找空闲的内存,而栈只需要没有栈溢出,就可以直接存储。


综上,栈使用最方便,最无脑,别人帮你分配好一切(系统,编译器),也珍贵(空间小,在作用域马上就被回收);而堆比栈麻烦的多,唯一的好处是可以自己动态分配较大空间。这么一来,还是真像以前那个C++老师说的那样,好东西还真都是放在栈里的。