C#栈和堆的讲解

OS和CLR通常将用于容纳数据的内存划分为两个独立的区域,每个区域都采用截然不同的方式来管理:栈(Stack)和堆(heap)。

(1)       调用一个方法时,它的参数以及它的局部变量需要的内存总是从栈中获取,方法结束后,为参数和局部变量分配的内存将自动还给栈,并可在另一个方法调用时重新使用。

(2)       使用new关键字和一次构造函数调用来创建一个对象时,创建对象所需的内存总是从堆中获取,使用引用变量,同一个对象可以从几个地方引用,对对象的最后一次引用消失以后,对象使用的内存就可以供重用(它可能没有被立即回收)。

(3)       所有值类型都是在栈中创建的,所有引用类型都是在堆中创建的。

2.堆内存和栈内存

(1)栈内存就像一系列堆叠越高的箱子:调用方法时,每个参数都被放入一个箱子,并将这个箱子放到栈的最顶部。每个局部变量也同样分配到一个箱子,并同样放到堆栈最顶部;方法结束后,它的箱子都会从栈中移除。

(2)堆内存则像散布在房间里的一大堆箱子,而不像栈那样每个箱子都严格重叠在另一个箱子上方,每个箱子都有一个标签,标记了这个箱子是否使用。创建一个对象时,运行库会查找一个空箱子,并把它分配给对象,对对象的引用存储在堆栈上的一个局部变量中。运行库会跟踪对每一个箱子的引用数量,一旦最后一个引用消失,运行库就会将箱子标记为“未使用”吗,将来某个时候,会消除箱子里的东西,使其真正的能够重用。堆内存是一种有限的资源,如果堆内存被耗尽,new操作将会抛出一个OutOfMemoryException,对象创建失败。

3.对上边理论的例子解释:

(1)例如: void Method(int param)

{

  Circle c;

  C=new Circle(param);

   ……

}

假定传给param的值是42.。栈中将分配出一小片内存(刚好能够存储一个int),并使用值42来初始化,在方法内部,还要从栈中分配除另一小片内存,它刚好能够存储一个引用,只是暂时不初始化而已。接着,需要从堆中分配一个足够大的内存区域来容纳一个Circle对象。这正是new关键字所执行的操作——它将运行Circle构造函数,将这个原始的堆内存转换成一个Circle对象。Circle构造函数也可能抛出一个异常,在这中情况下,分配给Circle对象的内存也会被回收,而且构造函数返回的将是一个null引用。

(2)比如创建一个对象:

    void Method( )

   {

      Customer cus;

      cus = new Customer();

       ......

   }

申明一个Customer的引用cus,在栈上给这个引用分配存储空间。这仅仅只是一个引用,不是实际的Customer对象!cus占4个字节的空间,包含了存储Customer的引用地址。接着分配堆上的内存以存储Customer对象的实例,假定Customer对象的实例是32字节,为了在堆上找到一个存储Customer对象的存储位置,.NET运行库在堆中搜索第一个从未使用的,32字节的连续块存储Customer对象的实例!然后把分配给Customer对象实例的地址赋给cus变量! 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值