【Unity主程手记(摘录)】第一章(四) - 委托和事件、拆箱和装箱

第一章(四) - 委托和事件、拆箱和装箱

提示:个人学习总结,如有错误,敬请指正。



一、委托(delegate)

delegate的实例,从功能上来讲,类似于C++的函数指针。
可以把委托理解为一个函数容器,由于委托可以被直接赋值,所以会有函数丢失的风险,


二、event

event 很简单,它在委托delegate上,又做了一次封装,这次封装的意义是,限制用户直接操作delegate委托实例中变量的权限。
其不在可以进行 =操作,但仍然保留+= 和 -=;


三、Action和Func

  • Action:C#封装好的委托写法,也会有函数丢失的风险。
  • Func: 带返回值

四、装箱和拆箱

  • 装箱:值类型实例转换为引用类型实例
  • 拆箱:值类型实例转换为引用类型实例

值类型是在声明时就初始化了,因为它一旦声明就有了自己的空间因此它不可能为null,也不能为null。

引用类型在分配内存后,它其实只是一个空壳子,可以认为是指针,初始化后不指向任何空间,因此默认为null。

	栈是本着先进后出的数据结构(LIFO)原则的存储机制,
	它是一段连续的内存,所以对栈数据的定位比较快速,
	而堆则是随机分配的空间, 处理的数据比较多, 无论如何, 至少要两次定位。
	堆内存的创建和删除节点的时间复杂度是O(logn)。栈创建和删除的时间复杂度则是O(1),栈速度更快。

	那么既然栈速度这么快,全部用栈不就好了。
	这又涉及到生命周期问题,由于栈中的生命周期是必须确定的,销毁时必须按次序销毁,
	从最后分配的块部分开始销毁,创建后什么时候销毁必须是一个定量,所以在分配和销毁时不灵活,
	基本都用于函数调用和递归调用中,这些生命周期比较确定的地方。
	相反堆内存可以存放生命周期不确定的内存块,满足当需要删除时再删除的需求,
	所以堆内存相对于全局类型的内存块更适合,分配和销毁更灵活。

值类型的数据存储在stack上,直接持有。

引用类型的真实数据存储在heap,持有该地址的指针。

装箱的内部操作:

装箱:
根据相应的值类型在堆中分配一个值类型内存块,再将数据拷贝给它。按三步进行。

  1. 第一步:在堆内存中新分配一个内存块(大小为值类型实例大小加上一个方法表指针和一个SyncBlockIndex)。
  2. 第二步:将值类型的实例字段拷贝到新分配的内存块中。
  3. 第三步:返回内存堆中新分配对象的地址。这个地址就是一个指向对象的引用了。

拆箱:
则更为简单点,先检查对象实例,确保它是给定值类型的一个装箱值,再将该值从实例复制到值类型变量的内存块中。


五、装箱、拆箱对执行效率有哪些影响,如何优化。

影响:由于装箱、拆箱时生成的是全新的对象,不断得分配和销毁内存会不但大量消耗CPU,也同时增加了内存碎片,降低了性能。

避免方法:

  • Struct 通过重载函数来避免拆箱、装箱。
  • 使用泛型
  • 通过统一实现的接口提前拆装箱

六、装箱、拆箱的实现细节(待更新)


附录

主程手记

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值