在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
在Unity中很多已经定义为结构体的数据结构
值类型与引用类型的区别这两篇文章讲得很好
虽然我们在.net中的框架类库中,大多是引用类型,但是我们程序员用得最多的还是值类型。
引用类型如:string,Object,class等总是在从托管堆上分配的,C#中new操作符返回对象的内存地址--也就是指向对象数据的内存地址。 以下是值类型与引用类型的表:
从这张图可以看出,class(类)实例化出来的对象,指向了内存堆中分配的空间
struct(结构)实例化出来的对象,是在内存栈中分配
所以,值类型和引用类型的区别就是:
1、它们存储的位置不一样
2、如果是引用类型,当两个对象指向同一个地方,修改某一个的时候,其它对象的值会发生改变
当说到类的实例是传引用时,实际过程是,先获取一个指针,它指向对象在内存中的地址,然后传递这个指针。这很重要,因为一个类的实例,实际上可能很大,包含了很多域甚至其他对象。在这种情况下,赋值和传递整个实例可能非常影响性能,这就为什么要用传地址来替代。
说到传值时,实际过程是,对这个变量进行全克隆/拷贝,然后传递这个副本,原始值不变。结构体就是值类型,它是传值的。这意味着,结构体是理想的小型数据结构。
由于引用类型在托管堆上分配,它只会在调用垃圾回收时才被清理。
值类型实在内存栈上分配,这就说明他们很容易被回收,而且不受垃圾回收的影响。
数据类型分隔为值类型和引用类型。值类型要么是堆栈分配的,要么是在结构中以内联方式分配的。引用类型是堆分配的。引用类型和值类型都是从最终的基类 Object 派生出来的。当值类型需要充当对象时,就在堆上分配一个包装(该包装能使值类型看上去像引用对象一样),并且将该值类型的值复制给它。该包装被加上标记,以便系统知道它包含一个值类型。这个进程称为装箱,其反向进程称为取消装箱。装箱和取消装箱能够使任何类型像对象一样进行处理。
2.Class可以继承父类,Struct不可以所有结构体都默认继承System.ValueType父类,所以不能继承别的父类,ValueType是值类型的基类,详见:https://msdn.microsoft.com/zh-cn/library/system.valuetype(VS.80).aspx
3.Struct必须在构造函数对所有变量赋值结构体中所有变量都必须在构造函数中初始化
4.Struct没有默认构造函数Struct不允许有参数为空的构造函数
5.Struct与class的性能上的优缺点关于值类型与引用类型的内存可以看这篇文章:https://msdn.microsoft.com/zh-cn/dd365372
值类型的实例化之后在内存的大小就是其所有内容物大小,也就是内容物内存越大、占用内存越大,存放在栈中,但是取值更快,不需要GC回收
引用类型把值存放在堆中,引用存在栈中,实例化时要在堆中取值,所以更消耗时间,但是更省内存,因为只用引用指针的大小,需要GC回收
6.Struct类型变量默认不可为空也就是说,不能写这个语句 struct != null,如果像这样做的话,一定要加上?,为它取值要加上Value,判断是否为空要用HasValue
Struct? struct = *****;
if(struct.HasValue)
struct.Value.***** = ****;
值类型后面加问号表示可为空null(Nullable 结构)
Nullable是.NET 2.0中新提供的一种用于标明一个值类型是否可以为空的技术。
对于一个类型,如果既可以给它分配一个值,也可以给它分配空引用null(表示没有任何值),我们就说这个类型是可空的。
因此,可空类型可表示一个值,或表示不存在任何值。例如,类似 String 的引用类型就是可空类型,而类似 Int32 的值类型不是可空类型。Nullable 结构支持将值类型扩展为可以为null,但不支持在引用类型上使用,因为引用类型本身就是可空的。
因为值类型的容量只够表示适合于该类型的值,因此它不可为空;值类型没有表示空值所需的额外容量。
例:public int? age;
等同 Nullable<int> 7.其他值类型还有一个特性就是一旦修改值,就会产生一个值类型的副本
引用类型修改值,不会产生副本,但所有有该引用的值都会被修改
8.扩充来自《深入理解C#》值类型很能干,它们不需要垃圾回收,(除非被装箱)不会因类型标识而产生开销,也不需要解引用。 在其他方面,引用类型显得更能干,在传递参数、赋值、将值返回和执行类似的操作时,只需复制4或8字节(要看运行的是是32位还是64位CLR),而不是赋值全部数据。 值类型传给一个方法时,就得复制他的全部数据。 根据性能进行设计之前,需要衡量不同的选择。 类型(不管是类还是结构体),拥有多少方法并不重要,每个实例所占用的内存不会受到影响。(代码本身会消耗内存,但这只会发生一次,而不是每个实例都发生) -update 2017/8/6 by wolf96 2017/7/19 |
请发表评论