值类型与引用类型的闲谈
一、CLR支持两种基本类型:值类型与引用类型。
1.值类型(Value Type)实例通常分配在线程的堆栈上,并上不包含任何指向实例的指针,因为变量本身就包含数据。其在MSDN的定义为:值类型直接包含它们的数据,值类型的实例要么在堆栈上,要么内联在结构中。值类型主要包括简单的类型、结构类型和枚举类型等。
2.引用类型(Reference Type),引用类型实例分配在托管堆上,变量保存了实例数据的内存引用。其在MSDN中的定义为:引用类型存储对值的内存地址的引用,位于堆上。引用类型可以是自描述类型、指针类型或接口类型。
二、.NET的内存分配机制
现在有MyStruct和MyClass分别代表一个结构和一个类
MyStruct myStruct = new MyStruct();
MyStruct myStruct2 = new MyStruct();
myStruct2 = myStruct;
值类型通常分配在线程的堆栈上,而每个变量或者程序都有其堆栈,不同的变量不能共有同一个堆栈地址,因此myStruct和myStruct2在堆栈中一定中用了不同的地址。因为值类型上不包含任何指向实例的指针,变量本向就包含数据,尽管经过了变量的传递,但实际的内存还是分配在不同的地址上,如果我们对myStruct2变显改变,显然不会影响到myStruct的数据。
MyClass myClass = new MyClass();
MyClass myClass2 = new MyClass();
myClass2 = myClass;
引用类型实例分配在托管堆上,因而myClass在堆栈中只是保存了其实例数据的引用地址,实际的数据保存在托管理堆中。所以,就有可能不同的变量保存了同一地址的数据引用,当数据从一个引用类型传递到另一个相同类型的引用类型变量时,传递的是其引用地址而不是实际的数据,因此一个变量的改变会影响另一个变量的值。另外,引用类型实例分配在托管堆上,但是根据实例的大小有所区别,例如:如果实例的大小小于85000Byte时,则该实例创建在GC堆上;而当实例大小大于等于85000Byte时,则该实例创建在LOH(Large Object Heap)堆上。
三、嵌套结构
嵌套结构就是在值类型中嵌套定义了引用类型,或者引用类型变量中嵌套定义了值类型。
1.引用类型嵌套值类型
如果类的字段为值类型,那么它将作为引用类型实例的一部分,也分配在托管堆上。
2.值类型嵌套引用类型
引用类型作为值类型的成员变量时,堆栈上将保存该成员的引用,而成员的实际数据还是保存在托管中。
由此,可以得出一个结论,那就是:值类型实例总是分配在它声明的地方,声明为局部变量时其被分配在堆栈上,声明为引用类型成员时其被分配到托管堆上;引用类型实例则总是分配在托管堆。
浙公网安备 33010602011771号