这篇文章大概会解决以下几个问题:
值类型是什么,引用类型是什么,
值类型和引用类型的区别
生命周期怎么说?怎么申请,怎么释放;
什么是装箱和拆箱。过程呢,怎么会触发装箱和拆箱呢
为什么值类型会更快?引用类型会慢一点
new操作符做了哪些东西
值类型是什么,引用类型是什么,
C#中的类型可以分为托管类型和非托管类型,这里我们只说托管类型。
托管类型可以简单分为两种,值类型和引用类型。
值类型的继承链为System.valueType,System.ValueType继承于System.Object。
而引用类型直接继承于System.Object。
C#中的基本类型里面int ,float ,double,demcial,char还有结构体等都是值类型。
引用类型,我们使用的class,接口,委托等。
值类型和引用类型的区别:
值类型在我们声明的时候就创建了,引用类型则需要使用new操作符。
内存分配位置:简单概括,引用类型分配在托管堆上,值类型在内存中的存放位置看他的具体环境,如果是局部变量,就是在线程栈上,如果是作为类的成员变量,则跟着类成员一起分配在托管堆上。
生命周期:值类型在作用域结束后立即回收,引用类型则是在没有对象引用之后在GC触发后回收,生命周期不确定。
复制:值类型复制的时候,是把数据复制成新的一份,内存中会存在两份值类型数据。引用类型则是声明了一个新的类型成员指针,同时指向旧的类型成员。两者引用的类型实例是同一份(浅拷贝);
什么是装箱和拆箱,以及何时触发装箱和拆箱?
值类型->引用类型,装箱
引用类型->值类型,拆箱
装箱和拆箱的时候做了哪些操作?
装箱:
1.系统在托管堆上分配内存,分配值类型各字段所需的内存量,类型对象指针及同步块索引
2.复制值类型实例至托管堆中。
3.返回对象的地址
拆箱
1.获取实例字段的地址
2.复制到栈的值类型中。
何时触发装箱?
1.显示装箱以外
2.在调用值类型中未实现的基类型中的函数,为了找到这个基类,需要使用类型对象指针,从而触发装箱。
为什么大家都说值类型会更快,引用类型慢?
值类型存储在线程栈上,使用的时候,需要做的只是移动栈指针,然后赋值;栈上的数据是连续的,CPU的Catch miss 会相应减少。
引用类型在使用的时候,会使用new函数来进行分配内存的操作。
首先,会在托管堆上分配内存,如果托管堆没有足够的空间,则会触发gc。
然后会对引用类型进行复制,最后返回引用类型的指针。
这样对比下来,值类型更快一点。
介绍一下new操作符做的事情
1.计算类型需要分配的字节数大小,分配内存。
2.初始化对象类型对象指针,同步块索引
3.调用类型的构造函数,传入new中的参数。
后记:
这篇文章的大部分内容是我看了《CLR Via C》#这本书得来的,推荐大家可以看看,如果有说的不对,望请各位指正。