值类型与引用类型变量探究

.Net将变量的类型分为引用类型和值类型两大类。使用int、double等数值类型所定义的变量属于值类型,除此之外,枚举类型和结构也属于值类型。类类型的变量属于引用类型,他们可以引用一个真实的对象。

.Net中的引用类型分为:类类型、接口类型、数组类型和委托类型。

值类型变量与引用类型变量的内存分配模型是不一样的,为此先区分下两种不同类型的内存区域:线程堆栈和托管堆

线程堆栈和托管堆

每个正在运行的程序都对应一个进程,在一个进程内部可以有一个或多个线程,每个线程都拥有一块内存,称为“线程堆栈”,大小为1M,用于保存自身的一些数据,比如线程函数中定义的局部变量、线程函数调用时传送的参数值等,这部分内存区域的分配与回收不需要程序员干涉。如下代码

void func()
{
    int i = 100;
    ........
    return;
}

CLR在执行函数func时会在线程堆栈中为它的局部变量i分配一个4字节的空间,并初始化为100,然后CLR执行剩余的代码,如果函数中还定义了其他局部变量,还会在线程堆栈中分配新的存储空间给这些局部变量。

当CLR执行函数func的return语句时,函数执行结束,CLR将负责回收分配给此函数的局部变量的内存,这一工作是自动进行的,大多数情况下程序员是不必理会的。

值类型变量所占用的内存单元是在线程堆栈中分配的。

另一块内存区域称为“堆”,在.Net这种托管环境下,堆由CLR进行管理,所以称为“托管堆”。
当用new关键字创建对象的时候,分配给对象的内存单元就位于托管堆中。

引用类型变量引用的对象所占的内存单元是在托管堆中分配的

引用类型变量的内存模型

测试代码如下:

class MyClass
{
    public int Value;
    public int[] Numbers = new int[10];
}

static void Main(string[] args)
{
    MyClass obj;
    obj = new MyClass();
}

代码中先是创建了一个引用类型变量obj,此时默认值为null,没有引用任何对象。下面用new关键字在托管堆中创建了一个NyClass类型的对象,此时obj的值为对象的首地址。此时的对象内存模型如下图所示。

 

引用类型变量obj生存于线程堆栈中,因为它是Main方法的局部变量,而MyClass对象生存于托管堆中,obj所代表的线程堆栈中的内存单元保存的是托管堆中NyClass对象的首地址。

由于引用类型变量和它所引用的对象生存于不同的世界,因此这两者其实是独立的,引用类型变量被销毁(比如定义它的方法执行结束时)并不意味它所引用的对象也会被销毁,这一对象有可能会继续生存一个相当长的时间。

如果是对象数组呢,它的内存模型是如何的呢?

MyClass[] objs;
objs = new MyClass[10];

创建完对象的内存模型如图:

由于数组对象本身是引用类型,所有不管数组元素是值类型还是引用类型,它所占用的内存都在托管堆上分配。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值