感谢陈总和森哥在收到鹅厂面试的时候把我推了过去
3.17早上成功被捞了起来,收到了晚上的电话面
面试官自我介绍
PCG 客户端
项目
- 介绍一下项目
- 实现哪些功能
- 遇到什么难点
- 有没有体现自己技术的难点解决
平时调试是怎么调试的?
打断点
听没听过条件断点
没有
条件断点
条件断点可以右键编辑断点,选择condition,设置条件。
如:当局部变量localVal<10时,才打断,可以大大节省debug的时间。
C++
静态链接和动态链接有什么区别
- 静态链接是在编译后进行链接,动态链接是在运行时进行链接。
- 静态链接的过程就已经把要链接的内容已经链接到了生成的可执行文件中,就算你在去把静态库删除也不会影响可执行程序的执行;而动态链接这个过程却没有把内容链接进去,而是在执行的过程中,再去找要链接的内容,生成的可执行文件中并没有要链接的内容,所以当你删除动态库时,可执行程序就不能运行。
- 静态链接库执行速度比动态链接库快。
- 动态链接会比静态链接节省空间
虚函数怎么实现的
虚函数的实现原理
虚函数是通过一个叫做虚函数表的机制实现的。
每个包含了虚函数的类都包含一张虚函数表。虚表是一个指针数组,其元素是虚函数的指针,每个元素对应一个虚函数的函数指针。
虚函数表是属于类的,不是属于对象的,也就是说一个类只有一张虚函数表。
虚函数表具体存放位置是由编译器决定的
如果normalize()是一个虚成员函数,那么以下的调用:
ptr->normalize();
将会被转换成
(*ptr->vptr[1])(ptr)
虚函数表存放的位置
虚函数表是全局共享的元素,即全局仅有一个。
虚函数表类似一个数组,编译期会为每个类对象创建一个
vptr
(虚表指针)指针,指向虚函数表虚函数表存储虚函数的地址,即虚函数表的元素是指向类成员函数的指针,而类中虚函数的个数在编译时期可以确定,即虚函数表的大小可以确定。
虚函数表存放在全局数据区。
虚函数表是编译器来选择实现的,编译器的种类不同,可能实现方式不一样,就像前面我们说的vptr
在一个对象的最前面,但是也有其他实现方式,不过目前gcc 和微软的编译器都是将vptr
放在对象内存布局的最前面。
vector和list的区别
vector
底层通过数组实现,支持随机访问,查找效率高,时间复杂度为O(1)
当capacity不够时,需要重新开辟空间
list
底层通过循环双链表实现,遵循STL前闭后开的原则。
底层没有连续的空间,只能通过指针来访问,查找数据需要遍历,时间复杂度为O(n)
迭代器
std::vector::iterator
支持+
、+=
、<
等操作符
std::list::iterator
则不支持
vector 的 erase 和 remove 的区别
erase
erase 是把指定位置的元素删除,然后返回元素下一个位置的迭代器
remove
remove只是把非指定元素向前移
如,12345
std::remove(vector.begin(), vector.end(), 3);
最后会变成 12455 相当于只是强行移位了,并没有改变
vector
的大小
C++11后的新特性
- auto
- nullptr
- for each循环
- lambda表达式
什么是lambda表达式
lambda表达式表示一个可调用的代码单元。可以将其理解为一个未命名的内联函数。
[capture list] (parameter list) -> return type { function body }
其中,capature list
是一个lambda所在函数中定义的局部变量的列表,return type
,parameter list
和function body
与普通函数一样,分别表示返回类型、参数列表和函数体。lambda表达式必须使用尾置返回来指定返回类型。
说了自己常用的情况,比如在写std::sort的时候,可以传递给第三个参数。
什么时候即使声明了inline但是编译器仍然不把它当inline
答的时候说的是,如果代码过长行数过长,因为inline是编译期展开,需要代码尽量简洁。
然后面试官告诉我说这个跟编译器有关
怎么在进入main函数之前执行一段程序
linux下gcc
C++ attribute
关键字可以通过更改函数属性如改为attribute (constructor)
就可以实现。
多数情况
在全局变量声明类,类初始化的时候会调用构造函数,此时可以在构造函数中运行程序。
在父类构造函数中调用子类虚函数会有问题吗
会,类初始化的时候是先初始化父类再初始化子类。
调用虚函数时,此时子类的大部分成员变量都处于未初始化状态,可能出现UB。
map和unordered_map有啥区别
- map底层是红黑树,unordered_map底层是哈希表
- map不允许重复,unordered_map可以重复
- map会自动排序
操作系统
什么是死锁
指各个进程互相等待对方的资源,导致各进程阻塞,无法向前推进
什么会导致死锁
- 对系统资源的竞争,各进程对不可剥夺的资源的竞争可能引起死锁,对可剥夺的资源(CPU)的竞争是不会引起死锁
- 进程推进非法,请求和释放资源的顺序不当。
- 信号量的使用不当,如生产者消费者问题中实现互斥的P在实现同步的P之前
产生死锁的必要条件:
- 互斥条件:对必须互斥使用的资源的争抢才会导致死锁
- 不可剥夺条件:进程保持的资源只能主动释放,不可强行剥夺
- 请求和保持条件: 保持着某些资源不放的同时,请求别的资源
- 循环等待条件:存在一种进程资源的循环等待链
总之,对不可剥夺的资源的不合理分配,可能会导致死锁。
死锁的处理策略
- 预防死锁。破坏死锁产生的四个必要条件中的一个或几个。
- 避免死锁。用某种方法防止系统进入不安全状态,从而避免思索(银行家算法)
- 死锁的检测和接触。允许死锁发生,不过操作系统会检测出死锁的发生,然后采取某种措施解除死锁。
进程间的通信方式有哪些
管道、共享内存、消息队列、信号量
管道有什么局限性?
这其实回答不出来,是面试官一步步引导的
- 管道只能是父子进程之间通信
- 管道只有固定的读写端,不可以同时收发
计网
TCP流量控制和拥塞控制
流量控制
发送端和接收端都维护一个接收窗口,知道对方发了多少和还可以接受多少
拥塞控制
维护一个拥塞窗口
- 慢启动
- 拥塞避免
- 快速恢复
HTTPS
HTTPS加密原理:SSL
HTTPS在传输内容上是对称加密还是非对称加密
对称加密
首先:非对称加密的加解密效率是非常低的,而 http 的应用场景中通常端与端之间存在大量的交互,非对称加密的效率是无法接受的。
另外:在 HTTPS 的场景中只有服务端保存了私钥,一对公私钥只能实现单向的加解密,所以HTTPS 中内容传输加密采取的是对称加密,而不是非对称加密。
视频直播用TCP还是UDP
UDP,因为不考虑精确性,更在意流畅度。
http有哪些方法
- get
- post
- put
- delete
- options
get和post有什么区别
GET的语义是请求获取指定的资源。GET方法是安全、幂等、可缓存的(除非有 Cache-ControlHeader的约束),GET方法的报文主体没有任何语义。
POST的语义是根据请求负荷(报文主体)对指定的资源做出处理,具体的处理方式视资源类型而不同。POST不安全,不幂等,(大部分实现)不可缓存。为了针对其不可缓存性,有一系列的方法来进行优化,以后有机会再研究(FLAG已经立起)。
还是举一个通俗栗子吧,在微博这个场景里,GET的语义会被用在「看看我的微博上最新的20条微博」这样的场景,而POST的语义会被用在「发微博、评论、点赞」这样的场景中。
有没有听过字节序
大小端
什么是大端小端
0x12345678
大端
0x12 34 56 78
小端
0x78 56 34 12
设计模式
优化if else可以用什么设计模式
策略模式
什么是观察者模式
一个改变通知全局
数据库
关系型数据库和关系型数据库有什么区别
回答不上来,数据库是我的死穴。
数据存储方式不同。
关系型和非关系型数据库的主要差异是数据存储的方式。关系型数据天然就是表格式的,因此存储在数据表的行和列中。数据表可以彼此关联协作存储,也很容易提取数据。
与其相反,非关系型数据不适合存储在数据表的行和列中,而是大块组合在一起。非关系型数据通常存储在数据集中,就像文档、键值对或者图结构。你的数据及其特性是选择数据存储和提取方式的首要影响因素。
扩展方式不同。
SQL和NoSQL数据库最大的差别可能是在扩展方式上,要支持日益增长的需求当然要扩展。
要支持更多并发量,SQL数据库是纵向扩展,也就是说提高处理能力,使用速度更快速的计算机,这样处理相同的数据集就更快了。
因为数据存储在关系表中,操作的性能瓶颈可能涉及很多个表,这都需要通过提高计算机性能来客服。虽然SQL数据库有很大扩展空间,但最终肯定会达到纵向扩展的上限。而NoSQL数据库是横向扩展的。
而非关系型数据存储天然就是分布式的,NoSQL数据库的扩展可以通过给资源池添加更多普通的数据库服务器(节点)来分担负载。
对事务性的支持不同。
如果数据操作需要高事务性或者复杂数据查询需要控制执行计划,那么传统的SQL数据库从性能和稳定性方面考虑是你的最佳选择。SQL数据库支持对事务原子性细粒度控制,并且易于回滚事务。
什么是事务
事务是由一系列对数据的访问与更新操作组成的程序执行逻辑单元。
事务有哪几个特性
- A: Atomicity, 原子性:事务是最小的操作序列单元,一个事务中包含的所有操作在一次执行后要么全部操作成功,要么全部操作失败,也就是说如果事务执行过程中出错,那么就会回滚到事务开始前的状态
- C: Consistency, 一致性:指事务的执行不能破坏数据库数据的完整性和一致性,例如A向B转账,如果事务中只给B的账户增加了余额而A的余额不变,那么就破坏了数据的一致性
- I: Isolation, 隔离性:不同的事务并发操作相同的数据时,每个事务都有各自完整的数据空间,不应互相干扰
- D: Duration, 持久性:事务一旦提交,对数据的修改便被永久保留
算法与数据结构
什么是桶排序
答不上来
补充
桶排序其实就是把一定范围内的数据放入桶中,再对桶中元素进行排序,达到局部有序,最后根据桶的顺序归并,形成全局有序。
什么是快排
简答了一下
哈希表听过吗?怎么解决哈希冲突
再哈希
定义间隔取下一位
如定义组数据,1、3、5、7、9,如果冲突了就+1,+1还冲突就+3,以此类推
链式哈希表,在冲突位置上接上链表。
结尾
后面就问了自己手上的offer,有没有意愿来腾讯,并且约了3.18一个代码面,可能是我的笔试成绩太差了。
3.18代码面
3.18凌晨刷了一夜的题
下午代码面问了两个题
- 最大重复子序列
- 顺时针输出矩阵
最后面试官让我优化一下第一题就算过了,说我好好准备一下复试。
求求鹅厂爸爸收了我吧!!!!!!
3.23更新复试
约了早上10点30的复试,面试官如约打电话进来了。
先是问了下手上的offer情况,然后问为什么选PC客户端
问会不会obj-c,然后就开始问了,基本问题问了很多二面的问题
TCP四次挥手
为什么需要四次挥手
AVL树介绍一下什么情况下需要旋转
MAP的底层结构是什么
听没听过QUIC
一百万个数字找最大的100个(用快排思想)
平时是怎么调试的
怎么判断程序崩溃的原因
HTTPS介绍一下
SSL过程描述一下
索引底层结构是什么
有没有办法加快查询速度?
索引是不是越多越好
大概就这些了,其他的东西我也记不住了…
再次球球腾讯爸爸收了我吧!!!!!