在clr中,new创建对象都做了哪些操作(.net)
用了好多年的new(创建对象),可是对于new背后都做了哪些操作,一直不清楚,经过两周的研究(不仅仅是看书上的理论,还要证明书上所说的是否正确),终于明白一些,现在来说一下:
工作内容
每当我们用new创建一个对象时,都会做如下操作:
1:计算类型的字段(以及从积累集成的字段)所需的字节数。
2:加上对象开销所需字节数。
- 类型对象指针:4字节(32位),8字节(64位);
- 同步快索引: 4字节(32位),8字节(64位);
3:clr检查区域中是否存在分配对象所需的字节。
- 如果托管堆有足够的空间,就在NextObjPtr指针指向的地址放入对象,为对象分配的字节会被清零。接着调用类型的构造器(为this参数传递NextObjPtr),new操作符返回对象引用。就在返回这个引用之前,NextObjPtr指针的值会加上对象占用的字节数来得到一个新值,即下个对象放入托管堆时的地址;
- 如果托管堆没有足够的空间,则会触发垃圾回收,然后再放入对象;
- 如下展示了包含三个对象(A、B、C)的一个托管堆:
对象占用空间
根据刚刚学到的理论,我们来验证下,创建对象占用多大空间。
举一个例子(在32位系统中):因为所占用空间和字段布局是有关系的,这里只说最常见的布局: [StructLayout(LayoutKind.Auto)],clr 会将两个bool型变量b1和b2放到相邻的位置中:
根据理论计算,创建People的一个对象要占用20byte:
验证----对象占用空间
1:通过windbg查看,people占用的空间为20byte,和理论值一样。
2:通过查看offset,也能证明布局和预期的一样。
因此无论是所占空间大小和空间布局都和预期的是一样的。
另外:
1:在托管堆上分配对象只需要在指针上加一个值-----速度相当快。
2:当在一个对象里面已用另外一个对象时,不会将另一个对象也算在当前对象上,在当前对象上只增加一个指针大小的空间:4byte(32位),8byte(64位)。
这就是我对clr创建对象的理解,哪里不对,还望指教。