【CLR】数据类型与装箱、拆箱

类型有:基元类型(int、long、bool等编译器直接支持的类型)、值类型、引用类型。

所有的类型都派生自System.Object

当我们new一个对象时,new操作实际做了这些事情:

  1. 计算当前类型及其所有父类,一直计算到System.Object,中定义的所有实例字段需要的字节数,这些实例字段的“类型对象指针”和“同步块索引”对象所需要的字节数。
  2. 从堆中分配这些字节,并初始化为0
  3. 初始化类型对象指针和同步块索引
  4. 调用类的构造函数

类型对象指针:当我们想查看某个对象是属于什么类型时,一般会调用GetType()或者typeof()方法,这个方法返回这个对象的具体类型,那么这两个方法怎么知道这个对象是什么类型呢?就是根据这个对象里的这个类型对象指针来找的,类型对象本质也是对象,所以就返回了这个对象。
同步块索引:线程同步用的,比如当我们lock住了某个对象,另外一个线程也执行到这里时,操作系统怎么知道是该阻塞还是该放行呢?就是根据这个同步块索引。具体的实现可以参考线程同步那篇文章。

装箱和拆箱

概念都不用解释了。值类型比引用类型“快”,主要是因为它们不在堆中分配,不需要被GC,也不用通过指针进行引用。
装箱
值类型转为引用类型,对应代码(object)a,主要发生了下面这些事情:

  1. 在托管堆中分配内存,所需内存的大小就是值类型各字段所需要的内存量+类型对象指针的内存量+同步块索引的内存量
  2. 将值类型的字段复制到新分配的堆内存中
  3. 返回这个对象的指针

拆箱
引用类型转为值类型,对应代码(int)obj,主要发生了这件事:

  1. 获取已装箱对象中各个字段在堆上的地址

拆箱不是简单的把装箱倒过来操作,拆箱简单的多,就是一个获取地址的操作。对于以下代码:
int a=(int)obj;其实有两步操作,第一步就是获取在堆上的地址,第二步是赋值操作引起的将堆上的内容复制到栈上的操作,这一步其实不属于拆箱。

相关推荐
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页