值类型与引用类型

一:C#语言中的数据类型

C#的数据类型分为两类:值类型(基本的数据类型)和引用类型
值类型:byte,int,float,bool,struct.....
引用类型:string,数组,自定义的类,内置的类.....
数组


二:堆和栈

咱们把内存分为堆空间和栈空间
栈空间比较小,可是读取速度快
堆空间比较大,可是读取速度慢ide

栈只能从栈顶插入或删除元素,相似于桶装的薯片,先进后出
堆可以以任意顺序插入或删 除元素,堆里面的每个元素都是程序中的一个引用

     spa


三:GC的简介

CLR中的GC(Garbage Collector 垃圾回收器)就是内存管理机制,C#中不须要咱们关心内存的使用,由于CLR帮咱们作了
例如在堆中一共有两个对象被程序引用着,当其中一个对象的引用断开,GC发现没有对象引用着它,那么会自动释放它的内存,释放后这块内存能够被重用3d


四:值类型和引用类型

值类型只须要一段单独的内存去存储实际的数据,通常在栈中存储
引用类型须要两段内存,一段存储实际的数据,在堆中存储,另外一段是一个引用,在栈中存储,指向数据在堆中的存放位置(内存地址)
orm

能够拿在一个盒子里装吃的来分析:
值类型就是在盒子里直接放了吃的
引用类型是在盒子里放了一张纸条上面写着吃的在哪个盒子里对象

Q:Unity中为何不能对transform.position.x直接赋值?blog


五:几种不一样状况下的内存存储

——第一种


当Test方法执行后会先清空栈中的内存,首先清空name的内存地址,而后清空bool类型变量c的内存,清空char类型变量b的内存,清空int类型变量a的内存,最后GC的引用计数器发现string类型liu的引用数为0,则释放堆中string类型liu的内存内存


——第二种(正常的引用类型)


当使用引用类型赋值时,其实赋值的是引用类型的引用(地址),并非实际值
当str[0]赋值b1时,操做的实际上是同一块内存空间,并非操做的新的内存空间string


——第三种(特殊的引用类型,string类型比较特殊)


当使用引用类型赋值时,其实赋值的是引用类型的引用(地址),并非实际值
当str赋值chen时,是系统在堆中又开辟了一段新的内存空间去存储string类型chen的实际值it


首先在堆中开辟一个内存空间(例如0X88)保存str1的值a1和a2,而后在栈中开辟一个内存空间保存地址0X88,当将str1赋值给str2时,是把str1的地址赋值给了str2的地址,即在栈中开辟了一个内存空间保存地址0X88,因此str1和str2引用着同一块堆中的内存空间,当把b1赋值给str2[0]时,操做的是地址0X88对应在堆上保存的值,因此str1和str2是同样的



首先在堆中开辟一个内存空间(例如0X88)保存str1的值liu,而后在栈中开辟一个内存空间保存地址0X88,当将str1赋值给str2时,是在堆中又开辟一个内存空间(例如0X11)保存str1的值liu,而后在栈中开辟一个内存空间保存地址0X11,接下来把chen赋值给str2时,是在堆中新开辟一个内存空间(例如0X22)来保存chen这个值,而后再把栈中str2保存的地址改成0X22,以后堆中0X11的内存空间会被垃圾回收掉

——第四种(比较容易混淆的)


v1,v2都是自定义类型,为引用类型,当执行v1=v2时,v1与v2的内存地址都引用了同一块堆中的实际内存区域,因此操做v1.x就至关于操做v2.x


——第五种


若是数组中的值是值类型,那么数组中直接存储值
若是数组中的值是引用类型,那么数组中存储的是引用(内存地址)

当执行Vector3 v1=v[0]时,v1的内存地址引用了堆中内存地址1,因此执行v[0].x与v1.x都是操做同一块内存空间


六:为何定义一个string类型的变量能够赋值null,而char类型的变量不能够

char类型是值类型,存在在栈上,在编译时要求分配内存,因此必须为其赋初值,其余值类型如int,double,枚举,结构等都是如此 string是引用类型,在栈上存储地址,堆上存储值,在程序运行时动态的分配内存,因此容许在变量声明时声明为null,不为其分配内存

相关文章
相关标签/搜索