游戏开发岗面经总结7(函数调用底层,值捕获和引用捕获,宏定义和内联,排序算法稳定性,static,软工思想,sprite和image的区别,细小物体碰撞问题)
Posted 头号理想
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了游戏开发岗面经总结7(函数调用底层,值捕获和引用捕获,宏定义和内联,排序算法稳定性,static,软工思想,sprite和image的区别,细小物体碰撞问题)相关的知识,希望对你有一定的参考价值。
函数调用底层
在了解函数调用之前首先我们应该知道堆栈存储区(五大存储区都应该了解)
栈:在函数运行之前自动分配好空间资源,函数运行完毕之后自动回收资源
堆:程序员手动申请,操作系统 进行算法分配,在进程结束的时候自动回收对应的堆空间资源
最好还是让程序员来回收
栈帧
上文提到 栈可以自动为函数调用分配空间资源 这种资源就是栈帧
栈帧的分配是从高地址向低地址逐步进行的
一个栈帧的大小不是无限的,靠近低地址的一端是栈顶,高地址一端是栈底
栈顶地址和栈底地址各自保存在自己专门的寄存器可称之为栈顶指针,栈底指针
栈帧的栈底指针减去栈顶指针就是栈帧的大小,所以可以通过栈顶指针的自增自减来控制栈帧的增大和减小
入栈
1.栈顶指针自减 扩大栈帧空间
2.某个寄存器的值保存到刚刚开辟的空间上
出栈
栈顶指针自增 缩小栈帧空间 将原来的栈顶的值赋予某个寄存器
函数参数入栈顺序为从右到左
为什么从右到左呢?
因为内存中的栈区 和数据结构栈的性质是一样的 都是先进后出
从右到左压栈 出来的时候 就是从左到右 得到我们想要的 效果
值捕获和引用捕获
lambda表达式里的“参数”是在调用的时候拷贝,”被捕获的变量“是在lambda表达式创建的时候调用
如果采用值捕获的方式 后续对变量的修改不会影响lambda的计算
如果采用引用捕获的方式,后续如果对变量修改,会影响到lambda的计算结果
说到值捕获和引用捕获 就提一下函数参数值类型和引用类型的区别
值类型:其实就是将原来的值 复制了一份 给函数作为参数传进去,当函数执行完成从栈中弹出 原来的值不会发生改变
引用类型:将引用变量空间中的内存地址复制了一份传入函数中去,当函数执行的时候会根据地址找到堆中的对象 导致原来的值发生改变
宏定义和内联和const
内联:
当程序调用内联函数,系统将函数中的代码插入到调用的位置上,实参代替形参 ,之后不再进行函数的调用
其实节省的就是函数调用的开销 如果函数中的内容比较复杂,则开销实际上比正常的函数调用更大
宏定义
#define定义的标识符不占用内存,只是一个临时变量,预编译后这个符号就不存在了
预编译不是编译,而是编译之前的处理,这个操作是正式编译之前系统自动完成的
#define 的功能是将标识符定义为其后的常量
一旦定义程序中就可以用标识符直接表示常量
变量名只是一个变量,宏只是一个常量,可以给变量赋值,但是不能给常量赋值
const和宏的区别
const可以在程序运行时调试,但是宏不可以
宏只是简单的字符串的替换,没有类型检查,const有对应数据类型,可以避免一些低级错误
宏是在程序中有多少次使用就替换多少次,宏定义在内存中有若干个备份,const的只读变量在内存中只有一个备份
宏是在编译的时候起作用,const是在编译运行的时候起作用
宏定义和内联区别
内联函数可以在运行的时候调试,宏定义不可以
内联函数可以访问类的变量,宏定义不可以
在类中声明同时定义的成员函数,自动转化为内联函数
编译器会对内联函数的参数类型做安全检查和自动类型转换 宏定义不会
排序算法稳定性
排序算法的稳定性不是简单的不同情况的时间复杂度的稳定性
而是数据的稳定性
举个例子 两个相等的值 排序之后他俩互换位置 这就是不稳定的
相反 两个相等的值,排序之后他俩的相对位置不发生改变 这就是稳定的排序算法
我们常用的 冒泡,插入,归并都是稳定的
快排 堆排序,选择,等是不稳定的
static
函数中的静态变量:
当变量声明为static类型的时候,这个变量被分配在全局数据区
即使多次调用这个函数,静态变量的空间只分配一次,前一次调用的变量会通过下一次函数调用传递
静态变量和全局变量一旦内存被分配,静态区的内存一直等全部结束后就能释放
类中静态变量
类中静态变量同理也是只初始化一次,这个静态变量由所有的对象共享,也就是这个原因, 静态变量不能再构造函数中初始化
静态成员变量再类内声明,类外定义
游戏开发中常用的单例模式
类中静态成员函数
静态成员函数不依赖对象,只能访问静态数据成员,或者是其他静态成员函数,
无法调用非静态成员函数,以及变量
静态类
静态类的生命周期一直到程序的结束,再main结束之后,才会调用静态类的析构函数
软工思想
复用 ,分而治之,优化
面试的时候可以结合项目来一起说
sprite和image的区别
**使用:**首先Image是基于canvas才能渲染的 sprite和普通游戏物体一样可以随意移动位置,缩放,旋转等参数
渲染: Image是基于Image组件和Canvas Renderer组件来渲染的 sprite是基于SpriteRenderer来渲染的
细小物体高速碰撞物体 没有产生碰撞检测
1.我们可以在初始位置和结束位置拉一根射线,判断射线是否和障碍物碰撞
如果碰撞即可检测 反之亦然
2.将检测方式改为连续检测,rigifdbody.collisionDetectionMode =CollisionDetectionMode.Continuous;
以上是关于游戏开发岗面经总结7(函数调用底层,值捕获和引用捕获,宏定义和内联,排序算法稳定性,static,软工思想,sprite和image的区别,细小物体碰撞问题)的主要内容,如果未能解决你的问题,请参考以下文章
游戏开发岗面经总结5(面相对象和面相过程的区别,多态,CG,设计模式,进程线程协程,动静态合批态,内存区域存放,指针和引用的区别,防止对象被拷贝,map和unordered_map)
游戏开发岗面经总结6(unity优化总结,全局变量和全局静态变量,NULL和nullptr的区别,拷贝构造函数和赋值运算符的区别,深浅拷贝,哈希碰撞,TOPK问题,野指针问题,堆和栈,内存泄漏)