background image

生长方向:对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方
向;对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。

分配方式:堆都是动态分配的,没有静态分配的堆。栈有 2 种分配方式:静态
分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配
由 alloca 函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是
由编译器进行释放,无需我们手工实现。

分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:
分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定
了栈的效率比较高。堆则是 C/C++函数库提供的,它的机制是很复杂的,例
如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据
结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小
的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数
据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,
堆的效率比栈要低得多。

从这里我们可以看到,堆和栈相比,由于大量 new/delete 的使用,容易造成
大量的内存碎片;由于没有专门的系统支持,效率很低;由于可能引发用户
态和核心态的切换,内存的申请,代价变得更加昂贵。所以栈在程序中是应用
最广泛的,就算是函数的调用也利用栈去完成,函数调用过程中的参数,返
回地址,EBP 和局部变量都采用栈的方式存放。所以,我们推荐大家尽量用栈,
而不是用堆。

虽然栈有如此众多的好处,但是由于和堆相比不是那么灵活,有时候分配大
量的内存空间,还是用堆好一些。

无论是堆还是栈,都要防止越界现象的发生(除非你是故意使其越界),因
为越界的结果要么是程序崩溃,要么是摧毁程序的堆、栈结构,产生以想不到
的结果,就算是在你的程序运行过程中,没有发生上面的问题,你还是要小心,
说不定什么时候就崩掉,那时候 debug 可是相当困难的:)

对了,还有一件事,如果有人把堆栈合起来说,那它的意思是栈,可不是堆,
呵呵,清楚了?

static 用来控制变量的存储方式和可见性

函数内部定义的变量,在程序执行到它的定义处时,编译器为它在栈上分配
空间,函数在栈上分配的空间在此函数执行结束时会释放掉,这样就产生了
一个问题: 

 

如果想将函数中此变量的值保存至下一次调用时,如何实现? 最

容易想到的方法是定义一个全局的变量,但定义为一个全局变量有许多缺点,
最明显的缺点是破坏了此变量的访问范围(使得在此函数中定义的变量,不
仅仅受此函数控制)。