.NET中的栈和堆

  过去的很长一段时间里,我的工作状态大概就是Edison Zhou大神文中提到的死循环:“加班 -> 没空学习 -> 老是写同等水平代码 -> 无法提升代码质量 -> 老是出BUG -> 老是需要修改 -> 加班 ->……”。出了问题不可怕,可怕的是不能发现问题并做出正确的纠正。为了破除这个循环,关键在于挤时间学习,就以此文作为我破除该循环的第一步。

  本文的内容主要源自于《C# 图解教程》和网络中各位大神的博客中堆.NET中的栈和堆的理解。

  .NET程序中使用两个内存区域来存储数据:堆 (这里指的是.NET应用程序内存中的堆和栈,不是数据结构中的堆和栈)

一、基本概念

1.1 栈

栈是一个内存数组,是一个LIFO(Last In First Out,后进先出)的数据结构。

栈存储几种类型的数据:

  • 某些变量的值;
  • 程序当前的执行环境;
  • 传递给方法的参数。

栈的几个普遍特征:

  • 数据只能从栈的顶端插入和删除。
  • 把数据放到栈顶称为入栈(push)。
  • 从栈顶删除数据成为出栈(pop)。

 

 1.2堆

堆是一块内存区域,在堆里可以分配大块的内存用于存储某类型的数据对象;与栈不同,堆里的内存能够以任意的顺序存入或移除。

程序可以在堆里保存数据,但不能显示地删除他们。CLR的GC(Garbage Collector,垃圾收集器)在判断程序代码将不会再访问某数据项时,自动清除无主的堆对象。

下图中阐明了GC的回收过程

二、强化理解

这个部分内容转自Edison Zhou的博客《【译】.NET中六个重要的概念:栈、堆、值类型、引用类型、装箱和拆箱》

为了理解栈和堆,通过代码举例来了解背后到底发生了什么。

public void Method1()
{
    // Line 1
    int i=4;

    // Line 2
    int y=2;

    //Line 3
    class1 cls1 = new class1();
}

代码只有三行,现在我们可以一行一行地来了解到底内部是怎么来执行的。

  • Line1:当这一行被执行后,编译器会在栈上分配一小块内存。栈会在负责跟踪你的应用程序中是否有运行内存需要
  • Line2:现在将会执行第二步。正如栈的名字一样,它会将此处的一小块内存分配叠加在刚刚第一步的内存分配的顶部。你可以认为栈就是一个一个叠加起来的房间或盒子。在栈中,数据的分配和解除都会通过LIFO (Last In First Out)即先进后出的逻辑规则进行。换句话说,也就是最先进入栈中的数据项有可能最后才会出栈。
  • Line3:在第三行中,我们创建了一个对象。当这一行被执行后,.NET会在栈中创建一个指针,而实际的对象将会存储到一个叫做“堆”的内存区域中。“堆”不会监测运行内存,它只是能够被随时访问到的一堆对象而已。不同于栈,堆用于动态内存的分配。
  • 这里需要注意的另一个重要的点是对象的引用指针是分配在栈上的。 例如:声明语句 Class1 cls1; 其实并没有为Class1的实例分配内存,它只是在栈上为变量cls1创建了一个引用指针(并且将其默认职位null)。只有当其遇到new关键字时,它才会在堆上为对象分配内存。
  • 离开这个Method1方法时(the fun):现在执行控制语句开始离开方法体,这时所有在栈上为变量所分配的内存空间都会被清除。换句话说,在上面的示例中所有与int类型相关的变量将会按照“LIFO”后进先出的方式从栈中一个一个地出栈。
  • 需要注意的是:这时它并不会释放堆中的内存块,堆中的内存块将会由垃圾回收器稍候进行清理。

现在我们许多的开发者朋友一定很好奇为什么会有两种不同类型的存储?我们为什么不能将所有的内存块分配只到一种类型的存储上?

如果你观察足够仔细,基元数据类型并不复杂,他们仅仅保存像 ‘int i = 0’这样的值。对象数据类型就复杂了,他们引用其他对象或其他基元数据类型。换句话说,他们保存其他多个值的引用并且这些值必须一一地存储在内存中。对象类型需要的是动态内存而基元类型需要静态内存。如果需求是动态内存的话,那么它将会在堆上为其分配内存,相反,则会在栈上为其分配。

 

转载于:https://www.cnblogs.com/FlareDream-KarlChen/p/9975850.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值