参考以下博文,我这里只是条记一下,原文会更加具体
c#底子系列1---深入明白值范例和引用范例
堆栈和托管堆c#
值范例和引用范例
赤色表现——“这啥?”(真实1个题目引出3个题目)
CLR支持的两种范例
引用范例:
引用范例从托管堆上分配,new操纵符会返回对象的指针——指向对象数据的内存位置的一个引用,引用范例转达的是对象的指针(string特别)。引用范例的变量都必要一次堆内存的分配。
值范例:
值范例一样寻常在线程栈上分配,一个值范例变量包罗了着实例的值,没有引用指针。
雷同点:
都是System.Object的子类。
值范例也可以继承接口。
差别点:
1、 值范例分配在堆栈上,引用范例在托管堆上分配;
假如一个引用范例的某个属性是值范例,这个值范例也分配在托管堆上。
2、 全部的值范例都是隐式密封的(sealed),不能继承。
3、 值范例的赋值逐字段的复制,频仍赋值也会造成性能上的压力;引用范例的赋值只是指针转达。
4、 引用范例额外有范例对象指针和同步块索引。
5、 值范例继承自System.ValueType;引用范例继承自System.Object,System.ValueType也继承自System.Object。System.ValueType重写了Equals和GetHashCode方法
性能:
值范例分配在栈上,在GC控制外,不会对GC造成压力;
引用范例分配在堆中,会影响到GC,每一次到堆的内存分配都有大概举行一次垃圾网络操纵。
装箱拆箱:
装箱是将值范例转化为引用范例,拆箱则是将引用范例转化为值范例。
装箱:
1、 在托管堆中分配好了内存,分配的内存量为值范例的各个字段必要的内存量加上托管上对象的两个额外成员(范例对象指针,同步块索引)必要的内存量
2、 值范例的字段复制到新分配的堆内存中。
3、 返回对象的地点,这个地点就是这个对象的引用。
拆箱:
1、 获取已经装箱的值范例实例的指针。
2、 把获取到的值复制到栈。
(拆箱只能还原为原先未装箱之前的范例)
装箱比力泯灭性能,还大概引起GC操纵 |