栈与堆的区别

关于内存的使用,栈(stack)和堆(heap)是非常重要的两个概念,网上讲解的资料也比较多,大家也应该知道栈和堆分别的用途是什么,接下来说一下我对栈与堆的本质区别的理解。

 

每个程序在运行时系统都会分配一块叫做栈的连续的内存区域,大小一般为1M或2M,是编译程序时指定的常数。堆则是系统中所有空闲的内存区域,因此是不连续的,而且有可能是虚拟内存。函数的调用和返回是通过栈来实现的,不细说了。程序中用到的变量(对象)所占据的内存空间既可以从栈上分配,也可以从堆中分配,区别如下:

 

1. 内存指针的性质不同

栈上面只能分配长度较小、大小固定的数据,变量的内存地址相对于栈指针的偏移量在编译时就可以确定,因而可以生成直接的内存访问的指令。

堆上面分配的空间大小在运行时指定,并且返回的内存地址只能在运行时得知,因此栈上需要有一个相应的变量来保存堆上分配的内存地址,地址的长度为32位或64位。于是访问堆上的内存单元只能通过间接访问的指令来操作。

 

2. 内存空间的回收方式不同

栈上面分配的内存在压栈和出栈的过程中自动分配自动回收,速度很快。

堆上面分配的内存则需要显式地释放掉或者做垃圾回收的处理,有可能会漏掉释放,造成所谓的内存泄漏。

 

理解栈和堆的概念对于编写正确的高效的程序非常重要,但是程序语言的语法对栈和堆的体现很隐晦。C++创建一个类的实例时,既可以指定在栈上分配,也可以指定在堆上分配。C#中值类型的变量在栈上分配,引用类型的变量在堆上分配,值类型的变量也可以通过装箱的方式在堆上分配,在unsafe代码中可以在栈上分配大小固定的字节数组,总的来说没有C++灵活。

 

最后做一个练习,思考一下下面的程序在运行中内存是怎样分配的:

 

public struct A
{
    
int field;
    List
<int> list = new List<int>();
}

public class B
{
    
int field;
    List
<A> list = new List<A>();
}

public class P
{
  
static void main(string[] args)
  {
      A a 
= new A();
      B b 
= new B();
      Console.Write(
"{0} and {1}", a, b);
  }
}

 

posted @ 2011-06-07 19:33  刘俊峰  阅读(679)  评论(2编辑  收藏  举报