c#堆跟栈

在c#中堆跟栈的区别

  • 在C#中,堆只有一种(表示堆内存),而栈有两种——一种是与堆对应的栈内存,另一种是与队列(Queue)对应的数据结构。============================我们先说后一种,因为其在工作中最常用,也最好描述。这里以它们的泛型版本为例。Queue 是先进先出的数据类型,Stack 是先进后出的数据类型。数据在二者内部皆是以T[]形式存在的,这也就是很多时候建议开发者尽可能在创建新实例时为其指定capacity的原因——避免重新创建数组和拷贝元素的开销。由于二者都实现了IEnumerable 接口,所以它们都可以通过foreach来遍历访问其中的元素。要清除它们存放的数据,以 Stack为例,依次取出不是不行,但最简单的方法是使用 Stack(T).Clear() 方法。这个方法内部调用了 Array.Clear()方法( 把值类型设置为默认值,引用类型设为null,如果引用类型数据没有再被引用,GC就会找时间把它们回收了,这一点将在下面详述),并将Stack(T).Count 属性设置为 0 。=============================接下来说内存中的堆区域和栈区域。这部分原理其实并不那么重要,因为MSDN上有详尽的使用约定和建议,只要遵守就OK了。这里栈的存取方式与数据结构的那个“栈类型”没什么区别,都是先进后出。然而堆和队列则不懂,它不遵循先进先出原则。先从局部变量开始看看他们有什么用。
>    void Test1()
>     {
>       var a=1; //a是Int32类型,值存储与栈中.
>       var b=new Object(); // b指向NewObject的引用(指针)存储于栈中,NewObject存储于堆中。
>       var c=a;//c的值存储于栈中(复制值)。
>       var d=b;// 指针存储于栈中(复制引用),指向堆中的那个NewObject。
>     /*此时,栈的结构大致如下:
>       d|指向NewObject的指针
>       c|1
>       b|指向NewObject的指针
>       a|1 
>     */
>     }// 函数(方法)退出时,栈中的数据被清空,·而·堆·中·的·NewObject·还·在·,只是再无引用,静待GC。

简单的说,在这里,值类型存储于栈中,引用类型存储于堆中(指针存储于栈中)。为什么装箱拆箱开销高:

void Test2()
{
  var a=1;//a是Int32类型,值存储与栈中.
  Object b=a; //先把1复制到堆中变为引用类型(装箱),然后对堆中的“1”的引用存到栈中。
  var c=(Int32)b;//把堆中的“1”复制到栈中变为值类型(拆箱)。
}

装箱拆箱过程多了好多步骤,所以效率高。另外值得一提的是, 结构是值类型的,所有的变量(成员)都会拷贝,这也就是为什么MSDN在使用值类型的建议中给出了那么多限制的原因,不过对于引用类型的成员而言,仅拷贝引用(指针)。String 是特殊的引用类型:目标对象不会变动,对目标的任何修改都是创建一个新的字符串实例。对于位于字符串池中的目标而言,即时没有被引用不会被GC掉,所以对于有安全需求的字符串而言,最好使用SecureString 进行存储,详情参考String.Intern Method (String)String.IsInterned Method (String)。接下来说说静态类型。静态类型的变量,无论是值类型还是引用类型,都全部存储于堆中。如果静态类型的变量是引用类型,那么除非将其设置为null,否则该变量指向的对象永远不会被回收。这说起来可能有些复杂,我们继续用代码来举例:static Object a=new Object(); //此时,NewObject1对象存储于堆上,而它的引用a也存储于堆上。

void Test3
{
  var b=new Object();// 此时,NewObject2对象存储于堆上,而它的引用b存储于栈上。
  a=b;//此时a的引用改为NewObject2,NewObject1再无引用,坐等回收。
}//此时栈被清空,b变量离开作用域失效。

概括一下以上的内容,基本上栈用于存储临时的数据(局部值类型和引用),当一个方法执行完毕后立刻自动清除;而堆用于存储引用类型的对象和静态的对象,依靠GC回收。 但这绝非堆栈用途的全部,如果有兴趣可以参考 汇编、 CLR 以及 垃圾回收 的相关资料 。另外有几点要注意:1.一个进程只有一个堆,一个线程只有一个栈。2.GC有一套非常复杂的机制,比如重定位与压缩,所以在很多时候应该使用 fixed 关键字来确保程序的稳定性。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值