游戏客户端面经整理2

游戏客户端面经整理2,第1张

1、static的作用

答:改变了对象的生命周期,使其出现在定义的时候到程序结束的整个时间段内,同时改变了对象的作用范围,使其只在定义它的文件内有效。



思路:作用+在类中使用的注意事项+与普通全局变量的异同
作用:保持变量内容持久,作用于局部变量时改变了局部变量的生存周期,使得变量存在于在定义后直到程序运行结束的这段时间;隐藏,作用于全局变量和函数,改变了他们的作用域,使得全局变量和函数只在定义它的文件内有效,在源文件中不具有全局可见性;作用于类的成员变量和成员函数,使得类变量和类成员函数和类有关,可以不定义类对象直接访问类的静态成员

在类中使用的注意事项:静态成员变量是在类内进行声明,在类外进行定义和初始化,在类外进行定义和初始化的时候不要出现static关键和和private、public、protected访问规则;静态成员相当于类域中的全局变量,被类的所有对象共享;静态成员变量可以作为成员函数的参数,普通成员变量不可以

与普通全局变量的异同:
同–都是静态存储方式
异–作用域不同、初始化不同-静态全局变量只初始化一次

2、this指针

答:表示对象本身的一个指针
思路:是什么+使用+创建+有效范围
是什么:每一个对象都能通过this指针访问自己的地址。


this指针是所有成员函数的隐含参数,在成员函数内部可以通过this指针来调用对象。



使用:this只能在成员函数中使用,成员函数的第一个参数为T* const register this;但是静态函数不能使用this指针,因为静态函数不属于具体一个对象,是整个类范围意义上的信息
创建:在成员函数开始执行前构造,在成员执行结束后清除
有效范围:只有在成员函数内才有定义,不能通过对象使用this指针,也无法知道对象this指针的位置,只有在成员函数中才可以

3、虚析构函数、虚拟继承

虚析构函数:为了当一个基类指针删除一个派生类的对象的时候,派生类的析构函数能够被调用,否则调用的会是基类的析构函数,会存在内存泄露
虚拟继承:菱形继承情况下会对同一基类的多次存储造成资源浪费,还造成了数据的二义性,虚拟继承解决了这一问题,虚继承的部分放在共享区域上

4、inline和宏定义的区别

思路:编译+是否为函数+类型检查
编译:内联函数在编译的时候展开,宏在编译预处理的时候展开;编译时,内联函数直接嵌入代码,宏只是简单的文本替换
是否为函数:内联函数是真正的函数,只不过在调用点处直接展开,而宏是关键字
类型检查:inline有类型检查,宏没有

5、引用是怎么实现的,为什么?

引用可以看做是一个变量的别名,编译器把用户的引用 *** 作看做const 指针;
引用的使用可以减少临时对象的拷贝

6、STL中存在的陷阱

迭代器失效:由于元素空间重新分配导致之前的迭代器访问的元素不在了

7、在什么情况下会发生拷贝

1、明确表示由一个对象初始化为另一个对象时
2、当对象作为函数的实参传递给形参时
3、当对象作为函数的返回值时

8、内存分区有哪些

思路:栈、堆、全局\静态存储区、常量存储区、代码段
栈:存放局部变量、函数参数、返回地址,由编译器自动分配和释放
堆:动态申请的内存空间,有malloc分配的内存块,由程序员控制分配和释放,在程序结束后还没有释放 *** 作系统会回收
全局/静态存储区:存放全局变量和静态变量,程序运行结束 *** 作系统自动释放
常量存储区:存放常量,不允许修改,程序结束后自动释放
代码区:存放代码,不允许修改,可以执行

9、sizeof和strlen的区别

思路:是什么+干什么+对字符数组的处理+生效时间+参数类型

sizeofstrlen
是什么C++运算符头文件函数
干什么测量字符数组分配的大小测量字符串的实际长度
对字符数组的处理字符数组作为形参,当做字符指针依然是字符数组
生效时间编译时计算长度程序运行期间(库函数)
参数类型可以是类型也可以是变量必须是char*类型
10、右值引用的作用,右值是什么

思路:什么是右值+什么是右值引用+move()
什么是右值:表达式结束后就不再存在的临时对象
什么是右值引用:绑定到右值的引用,通过&&获得,右值引用只能绑定到一个将要销毁的对象上,因此可以自由地移动其资源
move():可以将一个左值强制转化为右值,继而可以通过右值引用使用该值
作用:在拷贝构造的时候会有大量的构造和析构的调用,通过右值引用可以延长临时对象到函数中,避免了一些构造和析构。


在复制的时候也可以直接指向现有数据完成复制(C++ Primer P653)

int a = 42;						// a 为左值, 42是右值

什么是右值:

11、指针和引用的区别
指针引用
指向内容指针指向的内存空间在程序运行过程中可以改变引用所绑定的对象不能改变
内存空间占据内存空间相当于变量别名,不占内存空间
能否为空可以为空必须绑定对象
能否多级可以多级指针引用只能一级
12、vector的实现原理,map的实现原理(STL)

vector:序列式容器,三个普通指针扮演的迭代器构成vector数据结构,分别为指向空间头的iterator、指向目前空间尾的iterator和指向可用空间尾的iterator,维护一个连续的线性空间
list:是一个双向链表,只需一个指向node节点的指针,可以前后移动,每次插入和删除元素就配置和释放一个空间,迭代器不会失效
deque:双向开口的连续线性空间,
stack:先进后出的数据结构,deque封闭头端开口就是stack
queue:先进先出的数据结构,封闭deque底部出口,头部入口就是queue
heap:priority_queue的助手
priority_queue:底层是vector,使用heap形成的算法,以任何次序将元素推入容器,从优先级最高的元素开始取
slist:双向链表
map:红黑树

13、所有的构造函数包括哪些

思路:默认构造函数+带参构造函数+拷贝构造函数+类型转换构造函数+显示构造函数
默认构造函数:创建对象不传参,编译器会调用默认构造函数对对象进行默认初始化;编译器会在没有定义构造函数的类自动生成一个构造函数;定义了任意一个构造函数的类,编译器不会生成默认构造函数;默认构造函数可以由用户自己定义;如果一个类有一个成员对象,成员对象没有默认构造函数,这时候编译器不知道如何初始化在这个成员对象;最好自定义默认构造函数;
带参数构造函数:最普通的构造函数,利用传入参数初始化对象,有初始化列表这种写法
拷贝构造函数:在发生值拷贝的时候被调用,和赋值函数分清;如果没有定义拷贝构造函数,编译器会自动生成一个(浅拷贝)

Dog h(2, name);				// 带参构造函数
Dog x1 = h;							// 拷贝构造函数
Dog x2;
x2 = h;									// 赋值重载函数operator=()

类型转换构造函数:当构造函数只有一个参数的时候,且这个参数不是本类的const引用时,这种构造函数为转换构造函数
显示构造函数:限制构造函数的行为阻止奇怪的类型自动转换

14、用内存拷贝的方式直接拷贝vector本身会发生什么?会存在什么陷阱?

思路:什么是内存拷贝+拷贝vector会怎么样
什么是内存拷贝:内存拷贝函数void*memcpy(void*dest, const void*src,unsigned int count); ,由src所指向的内存区域复制count个字符到dest所指的内存区域。



拷贝vector会怎么样:复制后两个vector中的元素指向同一个地址,在析构的时候会出现指针被析构两次的错误,正确的做法应该是对复制的目标容器预先分配空间,这样在复制时不会指向一个地址

15、深拷贝、浅拷贝的区别

对于基本类型,深拷贝和浅拷贝是一样的,都是对原始数据的复制,修改原始数据不会对复制的数据产生影响
当数据成员中有指针时,浅拷贝使两个类中的两个指针指向同一个地址,当两个对象析构的时候会调用两次析构函数,导致指针悬挂的现象,这时候需要深拷贝。



区别:深拷贝会在堆内存中另外申请空间来存储数据

16、函数调用的过程

①准备参数(计算参数、传参)
②保存返回地址
☂控制转移至callee
④保存必要的caller现场

17、帧同步

思路:什么是帧同步+状态/帧同步
什么是帧同步:需要多个客户端表现效果一致(如王者荣耀十个玩家的屏幕显示的英雄位置完全相同、技能释放角度、释放时间完全相同)。


对大多数游戏,不仅客户端表现要一致,客户端和服务端的数据也要一致。



状态同步和帧同步的区别:核心在战斗逻辑在客户端还是服务端
状态同步:战斗逻辑在服务端,服务端接受客户端的 *** 作请求,服务端通知客户端具体 *** 作,并通知后续可能的效果
帧同步:服务端只负责转发客户端的信息

状态同步帧同步
流量消耗大,每次更改都要同步,一个 *** 作服务端需要通知客户端多次小,不需要同步属性,一个 *** 作只需服务端转发一次 *** 作
回放和观战更难,需要一个回放&观战服务器,游戏中服务器给客户端发消息的同时还需要把消息发给回放&观战服务器,在其他客户端申请回放或观看是,回放&观战服务器会把存储的消息发给客户端只需保存每局所有人的 *** 作
安全性高,因为所有逻辑和数值都在服务端,想作弊需要攻击服务器,比更改客户端困难很多因为所有数据都在客户端,解析客户端数据就可以(moba全图挂、吃鸡透视挂),可以通过比对同局其他人的战斗结果预防
服务器压力
开发效率占据主流,但是开发难度大,同一个功能需要客户端服务端共同完成开发难度低,PvP和PvE基本是相同的代码,服务器只需转发即可
断线重连把整个场景和人物根据服务端的数据重新生成一遍服务端把断线时刻到重连时刻的所有数据传给客户端,客户端加速游戏运行速度直到追上现有速度

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/578593.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-11
下一篇 2022-04-11

发表评论

登录后才能评论

评论列表(0条)

保存