在clr中,new创建对象都做了哪些操作(.net)

用了好多年的new(创建对象),可是对于new背后都做了哪些操作,一直不清楚,经过两周的研究(不仅仅是看书上的理论,还要证明书上所说的是否正确),终于明白一些,现在来说一下:

工作内容

每当我们用new创建一个对象时,都会做如下操作:
1:计算类型的字段(以及从积累集成的字段)所需的字节数。

2:加上对象开销所需字节数。

  1. 类型对象指针:4字节(32位),8字节(64位);
  2. 同步快索引: 4字节(32位),8字节(64位);

3:clr检查区域中是否存在分配对象所需的字节。

  1. 如果托管堆有足够的空间,就在NextObjPtr指针指向的地址放入对象,为对象分配的字节会被清零。接着调用类型的构造器(为this参数传递NextObjPtr),new操作符返回对象引用。就在返回这个引用之前,NextObjPtr指针的值会加上对象占用的字节数来得到一个新值,即下个对象放入托管堆时的地址;
  2. 如果托管堆没有足够的空间,则会触发垃圾回收,然后再放入对象;
  3. 如下展示了包含三个对象(A、B、C)的一个托管堆:
    在clr中,new创建对象都做了哪些操作(.net)

对象占用空间

根据刚刚学到的理论,我们来验证下,创建对象占用多大空间。
举一个例子(在32位系统中):因为所占用空间和字段布局是有关系的,这里只说最常见的布局: [StructLayout(LayoutKind.Auto)],clr 会将两个bool型变量b1和b2放到相邻的位置中:
在clr中,new创建对象都做了哪些操作(.net)
根据理论计算,创建People的一个对象要占用20byte:
在clr中,new创建对象都做了哪些操作(.net)

验证----对象占用空间

1:通过windbg查看,people占用的空间为20byte,和理论值一样。
在clr中,new创建对象都做了哪些操作(.net)2:通过查看offset,也能证明布局和预期的一样。
在clr中,new创建对象都做了哪些操作(.net)
因此无论是所占空间大小和空间布局都和预期的是一样的。

另外:

1:在托管堆上分配对象只需要在指针上加一个值-----速度相当快。
2:当在一个对象里面已用另外一个对象时,不会将另一个对象也算在当前对象上,在当前对象上只增加一个指针大小的空间:4byte(32位),8byte(64位)。

这就是我对clr创建对象的理解,哪里不对,还望指教。