虎牙C++后台开发实习面经(已拿offer)

985硕士,目前找暑期实习中,学校与虎牙同城,在offershow上查了一下待遇也不错,于是3月初投了简历,之前一直是用人部门筛选中,最近才约上了面试。

发现牛客网上虎牙的面经不多,于是贡献一篇,争取能走完三轮技术面

3.31一面,1h,电话面试


(以下回答中Q为面试官,A为我,派生类=子类,父类=基类,有些没有写回答的问题是回答上来了,并且扯了很多,因为不是很难,就没有具体记录我的回答了)

自我介绍+项目

看过什么C++书

后台开发是什么,与项目关系强吗(最后面试官说现在互联网公司不缺钱,买了大量的硬件,不需要人力那么强,可能跟我想的后台开发不太一样)

extern是什么---extern在变量前、extern "C"在函数前

Q:extern "C"在什么场景下使用

A:不需要虚函数重载的情况

Q:这是为了用而用,有没有不得不用的场景

A:只支持C编译器的开发环境下?

Q:那根本没法编译cpp了嘛,其实答得差不多了,当C++要作为库文件给C去调用时,不得不用

重载与覆盖有什么区别---重载的定义、覆盖的定义

Q:如何调用非虚的重载过的父类函数

A:static_cast可以吗

Q:emmm 这是一种方法吧,怎么样避免覆盖呢?

A:C++11支持的final关键字

Q:emmm final是避免虚函数进行重写吧?你可能没理解我的意思,父类有个非虚函数,我想在子类实现一个同名函数,但又不想覆盖父类,我想实现一种重载的机制

A:那我把这个返回值修改一下可以吗

Q:恐怕没有关系吧。emmm没事,想不起来就算了,这是比较生僻的语法。

析构函数为什么要声明为虚函数---内存泄漏

Q:在什么场景下没法析构呢

A:定义指向父类的指针,但是指向派生类,如果析构函数不是虚的,那么delete这个指针时,派生类的独有资源无法析构

Q:什么情况下派生类没有多余/独有资源

A:派生类没有自己定义新的数据成员,又没有重写虚函数

Q:如果重写了父类的虚函数,就会有多余的资源吗

A:对,因为重写虚函数,虚函数表要更新,而且派生类对象有一个虚函数表指针

Q:如果子类没有自己定义新的数据成员,只是重写了一个虚函数,那么它的内存体积会比父类大吗

A:emmm 应该是一样的,数据成员是一样的,非虚函数不占用类对象的内存空间,而父类与子类都有一个虚函数表指针,也是一样的

Q:如果在父类的虚析构函数中调用了虚函数,子类重写了这个虚函数,那在析构时,父类的析构函数中执行的虚函数是父类的还是子类的?为什么?

A:父类的,一般来说,在析构函数不应该调用虚函数,因为没法体现多态性,在析构时,顺序是先析构子类再析构父类,所以当执行基类的析构函数时,子类已经析构完了,所以虚函数只能是父类实体的

Q:子类没有重写父类的函数,但子类有自己的一些内置类型,如果父类的析构函数不是虚函数,那会产生内存泄漏吗

A:应该不会,巴拉巴拉(乱扯,什么堆空间)

Q:(拉回主线)我要delete一个类,类中的成员变量都是在堆上的,你再想想

A:(沉默了10s)我总觉得不会产生内存泄漏,可能是因为有什么内存回收的机制吧

Q:OK,那分析一下delete的过程

A:先析构,再回收空间

Q:用哪个函数回收呢?

A:delete operator - operator delete - C的free函数,牵涉到底层内存管理,

Q:free要指定长度吗

A:不用

Q:这是不是就是上一个问题的答案呢?

A:(恍然大悟)哦~所以这些成员变量相当于向前在类里面,在free类对象的时候也回收掉了

vector与list的区别---从连续内存与非连续内存的角度分析了一下性能

Q:vector当capacity不够时,需要重写申请空间-copy-销毁旧空间,这个时间复杂度是多少

A:单这个行为是O(n)

Q:那为什么push_back是O(1)呢

A:摊还分析,前面经历了很多次O(1)的push_back,这次O(n)push_back可以把时间摊还到前面去,所以整体是O(1)

Q:如果出现扩容,原本迭代器会失效吗,为什么?

A:vector迭代器底层是原生指针,指向原来的地址,扩容后需要搬运,所以原来的地址失效了

Q:那如果要你重新设计vector的话,要怎么样才能让迭代器不失效呢

A:迭代器中除了原生指针,还需要加入相对于begin()的偏移量

STL map底层是啥,为啥选红黑树不选AVL树,AVL树插入和删除最坏情况(O(n)),为什么不用B+树

Q:你说的B+树在数据库场景下能减少IO次数,应该指的是能减少IO次数,那如果是SSD有什么不同

A:(我的天,这是啥问题)这个。。。不太清楚

Q:那换个问题,SSD与机械硬盘的优缺点

A:(不是很清楚SSD的原理)SSD好像是什么二极管,有很多格子,用电激活起来,比较脆弱,随机读写性能更好。机械硬盘的随机读写性能比较差,因为它是有磁头的,磁头要去寻道,这牵涉到很多寻道算法,比如电梯算法,但是还是要移动磁头,所以性能较差巴拉巴拉

Q:emmm 差不多吧,不是因为SSD太强,而是因为对手太弱了

STL内存配置器有重写过吗(没有)

进程与线程的区别,线程私有变量是什么(回答不清楚,面试官说这是很关键的一个点,复盘时我才听清是thread local storage线程局部存储,不过我也不会)

多线程与单线程的优劣

STL容器是线程安全的吗(不是),有什么需要注意的(加锁与同步)

Q:多个线程读vector的内容需要加锁吗

A:不需要

Q:如果很多线程读,一个线程写,用什么锁比较好

A:读写锁吧

Q:读写锁有两种设计方式,一种是写优先、一种是读优先,写优先怎么做

A:写的时候,加锁,排斥其他的读

Q:读优先呢?

A:多个线程都能读,一个线程写的时候加锁

Q:emmm 读写锁本来就是要这样的(沉默了一会)OK吧,下一道题

C++11的atomic有听过吗(有),有几种内存模型(不知道)

服务端用accept,成功返回,说明三次握手完成了几次

A:(没搞懂他的问题,僵了好久)三次吧

Q:emmm ok,如果已经建立连接,那客户端如果连续发三次100字节的TCP包,那服务端有哪几种可能性呢

A:首先看不需要分片,100字节小于互联网场景的MTU,不需要分片,如果在不丢包的情况下,会收到三个包

Q:有没有可能收到一个300字节的大包

A:有可能,TCP是面向字节流的,服务端不知道消息的长度,在接收缓冲区读一定长度的字节,所以需要做粘包的处理

回到项目,华为比赛,可以用分布式吗,考虑一下

有写过分布式程序吗(没有),有了解分布式吗(知道CAP定理),现实中选择CAP中的哪项丢弃(A不能,CP看情况),什么情况下把P舍弃掉(我听错了,回答NoSQL把P舍弃掉了,复盘时才知道答非所问,面试官没说什么)

总结:很多问题都是从一个点出发,往深处挖,虽然有一些答不出来,但是还是挺有收获的。

4.2二面,45min,牛客视频

项目

STL容器有哪些(按照STL源码剖析的顺序讲了一遍)

Q:红黑树和哈希表,什么场景用呢

A:有序无序,时间复杂度(查找、插入/删除)、哈希表内存更大一点(一般是数据总量N*2,而且是质数)

Q:既然提到了内存,epoll里面是啥数据结构,为什么呢

A:红黑树,epoll_ctrl需要经常插入或删除,红黑树可以以更稳定的Ologn时间复杂度,哈希表在不断插入时可能需要rehash,在不断删除时原先开辟2N空间又会大大浪费

Q:emm这是内存的消耗,那我举个例子,假设TCP连接有十万个,内存消耗有多少呢?

A:单单一个TCP连接只消耗一个文件描述符fd,一个TCP连接有接收缓冲区与发送缓冲区,内存单位可能是K,取决于具体实现

Q:emm 是的,内存这也是一个点,但是在小场景下,哈希表浪费的内存也没有太大,有没有更重要的关注点

A:在时间上,哈希表可能需要rehash,红黑树在插入和删除后,最多两次还是三次就可以达到平衡,更加稳定

Q:emm 还有没有其他的点,可以影响到你红黑树与哈希表的选型呢

A:emmm

Q:工程上就是不断地取舍,再想想

A:(一番思考)我想到了一种场景,类似于数据库要用B+树的原因,要进入哈希表的数据需要经过哈希函数,可能会散落在哈希表各个地方,没有规律;红黑树是一种有序结果,相似的项目就在附近,所以遍历查找会更快一点

Q:(分析了一通)不是很确定,回头可以验证一下。其实还有个很重要的点,你没想到,那就是重载的问题,可能这个数据根本无法比大小

A:哦~嗯。。。那这个可能也算在有序无序的区别里面?

Q:也就是operator < 压根不能使用,这个时候不能用红黑树

A:哦~对对对,有道理

进程与线程的区别(巴拉巴拉,还说了一面完后学的thread local storage)

Q:(当我说到线程有自己独有的栈段与寄存器时,打断)为什么线程会有独有的寄存器,放在那里?

A:噢噢,我说的是程序计数寄存器

Q:emm 那放在哪里呢,比如我开一万个线程,就有一万个寄存器跑出来?

A:CPU里面吧,可能是L1 L2缓存里面,当我要调度下一个线程,就从缓存中把相应的程序计数寄存器读取出来(我的说法容易引起歧义,寄存器是一个个物理的、真实存在的元件)

Q:(解释了一通)寄存器应该是轮流占坑的东西

A:是是是是,我是这个意思

Q:有听说过协程吗

A:交织式的子程序,C++20,微信开源了协程库libco巴拉巴拉,具体怎么实现与应用场景坦白不是很清楚

Q:你说到了C++20,你对C++的新标准有什么了解呢

A:C++20有个Ranges,是对于区间范围的升华,好像传入泛型算法里的参数可以有更多的范围形式,巴拉巴拉,具体有点忘了

Q:如果想做左开右闭怎么办

A:把begin和end往前移一下

Q:ok 这不是很重要的事情

Q:条件变量为什么要传入一个锁,为什么不放在内部呢,就像printf一样,对缓冲区加锁解锁,用户不需要关心

(一来一回聊了很久,我始终没有答到点上,但是竭尽全力把自己的知识都吐出来了)

TCP与UDP的区别(我讲了很多很多,聊到自己搭建服务器用了bbr拥塞控制算法什么的)

Q:DNS为什么用UDP

A:包更多、对网络消耗更大、时间更多

Q:http dns有听过吗,就是用http来实现dns

A:(刚开始没听懂,解释了一番dns)哦。。是用http来做dns,没听过

Q:P2P,你觉得用TCP和UDP

A:我想想,点对点,我觉得是TCP吧,因为传输很大的字节流,要保证完整,所以我觉得是用TCP做的

Q:但是其实是用UDP做的

A:(尴尬)啊这样子的嘛。。(傻笑)

虎牙直播,弹幕的字数是1-30个字,后台有100w个敏感词数据库,怎么样实现屏蔽效果,注意是包含,可能有几个字是敏感词,也需要屏蔽

A:分词巴拉巴拉,nlp巴拉巴拉,布隆过滤器巴拉巴拉,哈希表巴拉巴拉

Q:分词属于nlp范畴了,感觉有点太过了,我想问的是nlp的一个子问题,而且我想要的是包含逻辑,不是匹配逻辑(特指布隆过滤器)

A:kmp算法?巴拉巴拉

Q:那得运行很多遍,不用这么复杂

A:(想了一会)好像在搜索引擎中,可以联想关键词,好像用到了一种叫做什么trie树来着

Q:那怎么具体怎么解决的呢

A:emm 具体有点不太了解

Q:ok我没什么问题了,你有什么问题可以问我

A:我想问一下刚才这道题,您最期待的答案是什么

Q:emm 这有很多种解法,有挫一点的也有高大上一点,比如AC自动机,树,或者自己构造一个树,trie树什么的

A:那虎牙直播是怎么解决的呢

Q:最开始我写的一个版本是用到了类似的,后来用了AI,现在还支持拼音,还有更多的组合,你可以自己写一写,挺有意思的

A:您觉得我还有什么提高的吗

Q:基础还可以,有些点没答上来(觉得我p2p那里没回答出来有点可惜),其他的还好

总结:面试官很友好,整个面试像一场技术探讨,很多东西我可以自由发挥,我说的一些点,面试官也在思考,感觉不错

半小时后HR电话,通过二面啦

## 虎牙三面

4.3 电话 15min

为了找C++后台开发岗位,你做了哪些准备

项目做了什么,有什么收获(每个项目都聊了一会)

网络编程了解多少(看了UNP、APUE,还看了陈硕大神写的Muduo网络库,但由于时间关系没来得及自己造轮子,巴拉巴拉)

半小时后HR电话,通过三面啦

## 虎牙HR面

4.3 电话 15min

为啥投虎牙,啥时候看虎牙直播的,对虎牙有其他了解吗

有投其他公司的吗,怎么抉择

啥时候能来实习

10min后(另一个)HR电话,get oc
#虎牙2021暑期实习春招##虎牙直播##实习##C++工程师##面经#
全部评论
确实有点难度的
1 回复
分享
发布于 2020-03-31 17:37
校友好!! 请问下“子类没有重写父类的函数,但子类有自己的一些内置类型,如果父类的析构函数不是虚函数,那会产生内存泄漏吗?”    这个是会泄漏吗?因为如果子类的成员变量是在堆空间分配的,而父类的析构函数不是虚函数,那么{Base* b = new Derived();delete b;} 就是未定义的,就会造成内存泄漏,这样理解对吗?
点赞 回复
分享
发布于 2020-03-31 21:58
阅文集团
校招火热招聘中
官网直投
楼主好!有投腾讯吗
点赞 回复
分享
发布于 2020-03-31 22:42
楼主大佬是拿到oc了吗,tql
点赞 回复
分享
发布于 2020-04-02 17:02
刚才面试了虎牙C++后台,C++部分问的几乎一模一样。。。幸好看了楼主面经 ,不然答不上来🤣
点赞 回复
分享
发布于 2020-04-02 18:34
看到这个。。。不敢说自己面的C++岗。。(楼主是真强。。
点赞 回复
分享
发布于 2020-04-02 21:47
感谢哈
点赞 回复
分享
发布于 2020-04-03 15:55
感觉楼主好强,是通过C++项目学习C++的吗?
点赞 回复
分享
发布于 2020-04-03 23:29
楼主最后选虎牙还是腾讯?
点赞 回复
分享
发布于 2020-04-04 10:33
你这个二面跟我简直一模一样啊,面试官好像很喜欢他做的那个弹幕检测敏感词的系统😂我也是这个问题聊了好久
点赞 回复
分享
发布于 2020-04-04 10:56
这个二面的问题跟我的简直一模一样😂
点赞 回复
分享
发布于 2020-04-06 19:08
可以请问一下楼主oc后多久拿的offer吗?等邮件一直等不来😭
点赞 回复
分享
发布于 2020-05-18 11:06
请问“如何调用非虚重载过的父类函数”这个问题应该是用 子类对象名.父类名::函数名 来调用子类“重载“过的父类同名函数吧,还有,严格意义上讲是不不应该说这种参数不同名字相同的子类函数叫子类重载,非虚的情况下应该叫重定义了吧,毕竟重载的概念一般出现在同一个类的情况,希望和楼主讨论确认下这个问题。
点赞 回复
分享
发布于 2020-05-22 17:23
楼主请问你现在在虎牙实习吗
点赞 回复
分享
发布于 2020-08-17 21:47

相关推荐

19 182 评论
分享
牛客网
牛客企业服务