您的位置:首页 > 其它

匿名类型&&堆和栈

2017-09-23 15:56 204 查看

匿名类型

在前面的代码中,我们创建变量(对象)的时候,都指定了变量的类型,但是我们也可以不去指定类型,这个就叫做匿名类型。

我们可以使用var声明一个匿名类型,匿名类型初始化的时候,这个变量的类型就被确定下来了,并且之后不能够在被修改。

static void Main(string[] args)
{
int i = 100;
var j = 1000;
j = 98;
j = "sdwd"; //j的类型已经被确定为int类型,不能够被修改了
var a = "asdwd";
var v1 = new Vector3();
}


在这段代码中我们可以看到j被确定为int类型之后不能够再被定义为string类型了。

堆和栈

堆和栈是程序运行时的内存区域,我们把内存分为堆空间和栈空间。

栈空间:空间较小但是读取速度快,数据只能从栈的顶端插入和删除,把数据放入栈顶称为入栈(push),从栈顶删除数据称为出栈(pop)。

堆空间:空间较大但是读取速度慢。与栈不同,堆空间的内存能够以任意顺序存入和溢出。

讲到程序运行的内存区域,就要谈到内存的回收。C语言里的内存管理可以由自己来完成,但是C#里面内存管理我们可以不用去关心,因为CLR(公共语言运行库)里的内存管理机制会自动帮我们回收无用的内存。(CLR在第一篇文章有大概的描述。)

内存管理机制又被称作GC(垃圾回收器),在堆空间中,一旦有对象不再被程序使用,垃圾回收器发现无主对象,就会释放该对象,释放之后,该对象占据的内存空间就可以重新被使用了。

值类型和引用类型

既然有堆和栈两种内存区域,那我们定义的变量是应该放在哪种区域呢?不同类型存放的区域是不一样的。

值类型:存放在栈空间(包括整数,bool,struct,char,小数这几种类型)。值类型只需要一段单独的内存用于存储实际的数据。

引用类型:存放在堆空间(包括string,数组,自定义的类,内置的类)。

引用类型需要两段内存:第一段存储实际的数据,这段内存总是位于堆中;第二段是一个引用,存放着内存地址,指向数据在堆中的存放位置,该引用位于栈中。

内存分析

当一个方法中同时有值类型和引用类型,在程序结束之后,GC会先释放一个在栈中的内存空间,然后检查堆空间有没有无主对象,有的话就释放该对象占据的空间,没有的话就释放栈的内存空间,循环往复。

当一个引用类型赋值给另一个引用类型的时候,并不是修改堆空间内的数值,而是修改栈空间的里的内存地址。

static void Test3()
{
string name = "lymon";
string name2 = "baidu";
name = name2;
Console.WriteLine(name + name2);
}


在这段代码中,name2赋值给name,实质上,name指向的是“lymon”这段数据,当赋值之后,name就指向了“baidu”这段数据,而“lymon”这段数据没有被修改,只是没有被栈空间里的数据引用了。

和上面的情况一样,一个引用类型赋值给另一个引用类型,那么当内村回收之后,堆空间只剩下一块内存空间,被赋值的引用类型的堆内存消失,这时候两个引用类型都指向同一段数据,无论怎么修改,都是修改同一块内存空间。

static void Test4()
{
Vector3 v = new Vector3();
v.x = 100;
v.y = 100;
v.z = 100;
Vector3 v2 = new Vector3();
v2.x = 200;
v2.y = 200;
v2.z = 200;
v2 = v;
v2.x = 300;
Console.WriteLine(v.x);
}


Vector3是只定义了x,y,z的类。当v赋值给v2时,v2指向的堆内存的数据就消失了,这时v和v2指向的都是v的数据,所以当v2.x=300的时候,v.x的值也为300。

还有一种更复杂的情况,就是引用类型的嵌套。

例如在数组中,存储的是值类型的数据,那么在数组中直接存储值;但是数组里要是存储的是引用类型的数据,那么数组中存储的就是内存地址了,然后内存地址再去指向数值。

static void Test5()
{
Vector3[] vArray = new Vector3[] { new Vector3(), new Vector3(), new Vector3() };
Vector3 v1 = vArray[0];
vArray[0].x = 100;
v1.x = 200;
Console.WriteLine(vArray[0].x);
}


在这个例子中,vArray数组中存的是三个引用类型,vArray在栈中存储了一个内存地址,指向堆空间的一段数据,该数据又存储了三个内存地址,分别指向xyz数值。



整个程序的内存关系大概就是这个样子。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: