【转】对C# 中堆栈,堆,值类型,引用类型的理解

news/2024/7/20 12:41:02 标签: 数据结构与算法, c#, 内存管理

对C# 中堆栈,堆,值类型,引用类型的理解

1,什么是GC GC的全称是garbage collection,中文名称垃圾回收,是.net中对内存管理的一种功能。垃圾回收器跟踪并回收托管内存中分配的对象,定期执行垃圾回收以回收分配给没有有效引用的对象的内存。当使用可用内存不能满足内存请求时,GC会自动进行。在进行垃圾回收时,垃圾回收器回首先搜索内存中的托管对象,然后从托管代码中搜索被引用的对象并标记为有效,接着释放没有被标记为有效的对象并收回内存,最后整理内存将有效对象挪动到一起。这就是GC的四个步骤。 由上可见,GC是很影响性能的,所以一般说来这种事情况还是尽量少发生为好。 为了减少一些性能影响,.net的GC支持对象老化,或者说分代的概念,代是对象在内存中相对存现时期的度量单位,对象的代数或存现时期说明对象所属的代。目前.net的垃圾回收器支持三代。每进行一次GC,没有被回收的对象就自动提升一代。较近创建的对象属于较新的代,比在应用程序生命周期中较早创建的对象的代数低。最近代中的对象位于零代中。每一次GC的时候,都首先回收零代中的对象,只有在较低代数的对象回收完成后仍不能满足需求的情况下才回收较高代数的对象。

2,读文章,看到了一个关于堆和栈(堆栈)的区别的比喻。很形象: 使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。 使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。

3,GC和堆栈、堆 由前述堆栈和堆的概念可以看出,堆栈不存在垃圾收集的问题,只需要直接压栈即可,而堆,则面临着很复杂的垃圾回收的问题。GC完全是对堆进行操作的,而对堆中对象是否有效的判断则是通过遍历堆栈来实现的。这里涉及到一个引用计数的概念,引用计数是对堆中对象被引用次数的统计,当一个对象的引用计数为零了,那么这个对象就可以被回收了。在进行GC的时候,垃圾回收器遍历堆栈,当发现一个堆地址的时候,它就将堆中该地址上的对象的引用计数加1,然后销毁堆中所有引用计数为零的对象,回收内存并整理堆中的碎片。

4,类实例化的步骤 类是最常见也是我们用的最多的一种引用类型,我们知道实例化一个类使用的是一个我们司空见惯的语句: ClassA ca = new ClassA(); 那么这短短的一句话中,计算机又做了些什么事情呢? 实际上,计算机在这个过程中大致做了这么几件事: 首先,在ClassA ca的时候,生成一个空的引用指针,并将它推入堆栈中: 然后,在new ClassA()的时候,生成ClassA的新的实例,并放入堆中: 在赋值号=这一步,将ca的引用指针指向刚刚生成的新实例: 这个时候,才算完成了整条语句的操作。

5,特例:string 类型与堆 大家知道,string类型是一种引用类型。但它又有一些值类型的特征。比如指向同一个字符串的两个string变量,如果其中一个变量值发生了改变,却不会影响到另外一个string变量。这就是因为: (1)CLR使用了一种叫字符串驻留的技术,对于 string   str1="abc"; string   str2="abc"; 当CLR初始化时,会创建一个内部的散列表,其中的键为字符串,值为指向托管堆中字符串的引用。刚开始,散列表为空,JIT编译器编译方法时,会在散列表中查找每一个文本常量字符串,首先会查找"abc"字符串,并且因为没有找到,编译器会在托管堆中构造一个新的指向"abc"的String对象引用,然后将"abc"字符串和指向该对象的引用添加到散列表中。   接着,在散列表中查找第二个"abc",这一次由于找到了该字符串,所以编译器不会执行任何操作,代码中再没有其它的文本常量字符串,编译器的任务完成,代码开始执行。执行时,CLR发现第一个语句需要一个"abc"字符串引用,于是,CLR会在内部的散列表中查找"abc",并且会找到,这样指向先前创建的String对象的引用就被保存在变量s1中,执行第二条语句时,CLR会再一次在散列表中查找"abc",并且仍然会找到,指向同一个String对象的引用会被保存在变量s2中,到此s1和s2指向了同一个引用,所以System.Object.Equals(s1,s2)就会返回true了。 (2)当使用重载操作符”=”给string对象赋值时,string的对象是引用类型,它保留在堆上,而不是堆栈上.因此,当把一个字符串赋给另一个字符串时,会得到对内存中同一个字符串的两个引用.例如,修改其中一个字符串,就会创建一个全新的string对象(注意,这个过程发生在”=”中),而另一个字符串没有改变.
6,C#中值类型分配在堆栈中。 值类型:bool,byte,char,decimal,double,enum,float,int,long,sbyte,short,struct,uint,ulong,ushort. 7,C#中引用类型分配在堆中,在堆栈中创建一个指向到堆的引用,返回给声明的变量。 引用类型:class,delegate,interface,object,string
备注:1. 值类型数组虽然分配在堆上,但数组元素依然是值类型,并没有被装箱。         2, 引用对象的值类型成员也随对象一起分配在堆上,同样也还是值类型,没有被装箱

转载于:https://www.cnblogs.com/zhangzheny/archive/2012/04/16/2451240.html


http://www.niftyadmin.cn/n/951910.html

相关文章

10冰点还原安装不了_win7纯净版系统玩dnf出现启动不了的问题

有不少深度系统的win7纯净版用户,都喜欢玩dnf这款游戏,但是会经常遇见玩dnf游戏启动不了的问题,现在为大家带来win7系统下dnf启动不了的解决方法。解决方法1:1、在双击程序时弹出“图形系统组建失败”的错误对话框,则有…

【转】C#装箱与拆箱

C#装箱与拆箱 要掌握装箱与拆箱,就必须了解CTS及它的特点。 NET重要技术和基础之一的CTS(Common Type System)。顾名思义,CTS就是为了实现在应用程序声明和使用这些类型时必须遵循的规则而存在的通用类型系统。.Net将整个系统的类型分成两大类 ——Value…

CSS3弹性盒模型Flex布局新旧混合写法详解(兼容微信)

flex是个非常好用的属性,如果说有什么可以完全代替 float 和 position ,那么肯定是非它莫属了(虽然现在还有很多不支持 flex 的浏览器)。然而在移动开发中,本来绝大多数浏览器(包括安卓2.3以上的自带浏览器…

delphi treeview 怎么改变单个节点的颜色_2020江苏省美术统考改变了什么

12月初的江苏美术统考科目仍是三项,上午考【1】速写(干活的人)和【2】素描(男青年)下午考【3】色彩(带水罐的静物)素描120,色彩120,速写60。总分300分,但是三项都在改变。当然,所有的试卷都是高清黑白相片,…

管理好程序中的DLL【转】

1个项目中用到了很多DLL,而NET默认只能把这些DLL全部和EXE程序放在同1个目录下,而我想把所有控件功能的dll放在1个Control的文件夹下面,这样方便管理。 要实现上面的功能很简单,首先为程序加个应用程序配置文件app.config,代…

弹性盒模型新旧版本对比总结

因为我之前已经将新版本和旧版本的弹性盒模型研究过,并且转载了我认为比较好的文章,所以这里不再对他们进行详细的介绍,如果想要了解更详细的请点击 新版本弹性盒模型:https://blog.csdn.net/lhjuejiang/article/details/80019673…

20分层打印_浅谈3d打印机的工作原理

3D打印技术出现在20世纪90年代中期,实际上是利用光固化和纸层叠等技术的最新快速成型装置。它与普通打印工作原理基本相同,打印机内装有液体或粉末等“打印材料”,与电脑连接后,通过电脑控制把“打印材料”一层层叠加起来&#xf…

windebug使用

1.从进程中dump出dmp文件。从进程管理里 点击 【创建转储文件】 2.打开windebug,设置Symbol path :srv*DownstreamStore*http://msdl.microsoft.com/download/symbols (这里注意这个网址一定要能打开) 3.设置Image path 4.打开 dm…