拆箱跟装箱内存分配与数据拷贝

拆箱跟装箱内存分配与数据拷贝
demo1:
int i=100;
object o=i;
i=200;
在这个实例中,程序执行了一个装箱操作。CLR为对象o在GC堆上分配了一块内存区,并把i中的数据100拷贝到了o的内存块中。注意:这里是拷贝,不是搬移,所以在Stack上还是有一块内存存储着i的。当执行到i=200的时候,所改变的是Stack上i的值,而GC堆上o的值并没有被改变。
这个实例可能比较好理解,再看下面的实例。
demo2:
int i=100;
object o=i;
object a=o;
a=300;
这里程序执行了两个装箱操作。第一次:object o=i;第二次:a=300;
这个实例前面两条语句好理解了。object a=o;这时CLR并没有为a分配内存块(因为object 是引用类型),CLR只是返回了一个指针指向了a所指向的那块内存(o和a其实都只是一个指针而已)。当执行到a=300;的时候,这是第二次装箱,前面说过了,装箱是数据拷贝,所以此时CLR会分配一块内存块,把300这个值放到这个内存块中,并且把a的指针更改,指向300这块内存。可以看出,此时o跟a是指向了不同的内存块了。GC.ReferenceEquals(o, a);返回的是false;
到这里可能也还好理解,在看下面的实例。
demo3:
public class Class1
{
   public int i;
}

static void Main()
{
   Class1 class1=new Class1();
   class1.i=100;
   Class2 class2=class1;
   class2.i=200;
   class2=null;
}
在这个实例中,程序没有执行任何的装箱操作。因为Class1这个类型中的i是一个值类型的,这个要注意:值类型并非都是分配在Stack上的,这里所说的值类型是一个引用类型中的值类型。它是分配在GC堆上的,程序中class1跟class2是指向同一块内存区的,它们所做的操作都是对这块内存区中的数据进行操作。所以最终i的值是被class2更改为200了。
原文地址:https://www.cnblogs.com/bmrxntfj/p/818243.html