[c/c++后台开发面经系列]3 bigo/映客面经(含答案)

此系列内容以及观点仅个人感受,不妥之处直接私我!目的为了大家能更好的知道面试题难度以及如何准备,希望能让大家少浪费时间寻找资料,多点时间学点干货!因为篇幅原因,大部分题目题解简洁,但有相关资料推荐进阶阅读,学会使用搜索引擎是一门艺术!望谅解!

两个公司岗位都是后台开发工程师,公司共同点都是直播,短视频相关,其面试中问到的题目为常见题目,所以不要怕。bigo四面为电话+视频。映客直播一共三面,但是必须现场笔试,如果通过一面第二天当场面试,嘻嘻,说实话,小姐姐的确多!

一 Bigo面试

一面,二面,三面间隔时间比较长,问题直戳中心(感觉蛮厉害),每轮几乎都有手撕算法,不过可能运气还行,常见题!

1 一面(视频面40分钟)

  • 自我介绍

主要表明自己姓名,学校,为什么面这个岗位或者公司,具有XX技术,想尝试贵公司等。

  • 析构函数是否可以为虚函数?为什么?

首先,析构函数可以为虚函数,原因:

 在实现多态时,当用基类操作派生类,在析构时防止只析构基类而不析构派生类的状况发生。一般情况下,用基类指针指向派生类对象,删除基类指针,这样的删除只能够删除基类对象,而不能删除子类对象,形成了删除一半形象,造成内存泄漏。在公有继承中,基类对派生类及其对象的操作,只能影响到那些从基类继承下来的成员。如果想要用基类对非继承成员进行操作,则要把基类的这个函数定义为虚函数。析构函数自然也应该如此:如果它想析构子类中的重新定义或新的成员及对象,当然也应该声明为虚的.

如果不需要基类对派生类及对象进行操作,则不能定义虚函数,因为这样会增加内存开销.当类里面有定义虚函数的时候,编译器会给类添加一个虚函数表,里面来存放虚函数指针,这样就会增加类的存储空间.所以,只有当一个类被用来作为基类的时候,才把析构函数写成虚函数.

  • 虚函数和纯虚函数的作用和区别

虚函数引入原因:为了方便使用多态特性,我们常常需要在基类中定义虚函数。

纯虚函数引入原因:

1、为了方便使用多态特性。

2、在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出狗子、猫等子类,但动物本身生成对象明显不合常理。纯虚函数就是基类只定义了函数体,没有实现过程(其实可以在类外部实现函数体)。

虚函数和纯虚函数的区别:

带纯虚函数的类叫抽象类,抽象类不能实例化,而能被继承,并重写其纯虚函数后,才能使用。

  • 说说tcp三次握手/四次挥手,加上相关的状态

TCP状态转化图(引自51)

可以考虑从一次完整的会话来回答,这样思路会更加的清晰。

  • 使用过epoll?为什么用它

不管是java还是c++还是what,网络通信的相关模式思路都是一致,能少轮询就少轮询,能使用缓存尽量使用,所谓局部性原理,非常的重要!再比如说消息队列中的kafka,为了削减高峰(上游流量),采用kafka缓解上下文的计算能力,这也是类似的思想吧!如果你想看epoll源码注释,后台回复[epoll]即可!

  • 介绍一下http与https及区别

HTTPS和HTTP的区别

超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息。HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的传输报文,就可以直接读懂其中的信息,因此HTTP协议不适合传输一些敏感信息,比如信用卡号、密码等。

为了解决HTTP协议的这一缺陷,需要使用另一种协议:安全套接字层超文本传输协议HTTPS。为了数据传输的安全,HTTPS在HTTP的基础上加入了SSL协议,SSL依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。

HTTPS和HTTP的区别主要为以下四点:

一、https协议需要到ca申请证书,一般免费证书很少,需要交费。

二、http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议。

三、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。

四、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全(相对安全)。

  • 编程题1 反转链表

c++版本
java版本
python版本

这个问题一般来说会有下文,只要不问一些敏感话题就行了。

2  二面(视频面40分钟)

忘记相隔了多少天,某一天晚上一个小姐姐打电话约时间面试。

  • 自我介绍

  • 讲一个你熟悉的项目,当时讲了一个跨网通信程序,引发不少问题出来。(所以,面多了你就知道简历怎么修改,怎么引导面试官问你问题了吧)

  • 遇见过粘包现象吗,如何避免

1 如果是发送方引起的粘包现象,我们可以通过操作指令让其不等待缓冲区满就直接发出。缺点是它会关闭优化算法,从而降低网络发送效率。

2 如果对于接收方引起的粘包,可以考虑通过提高接收进程的优先级,让其及时接受数据。缺点是,发送频率稍微一高,接收方仍然来不及处理,所以粘包可能性还是很大。

3 接收方进行控制,将数据分为多段多次接收,最后合并缺点就是对实时应用的场合不太适合。

4 接收方创建一预处理线程,对接收到的数据包进行预处理,将粘连的包分开。

面试官:我们看几个简单题

  • 构造函数为什么不能是虚函数?

虚函数的调用需要虚函数表指针,而该指针存放在对象的内容空间中;若构造函数声明为虚函数,那么由于对象还未创建,还没有内存空间,更没有虚函数表地址用来调用虚函数。

  • 父进程先退出了,子进程会咋样?

会被init进程回收。

  • 智能指针内部实现(C++11)

智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象共享同一指针。每次创建类的新对象时,初始化指针并将引用计数置为1;当对象作为另一对象的副本而创建时,拷贝构造函数拷贝指针并增加与之相应的引用计数;对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数(如果引用计数为减至0,则删除对象),并增加右操作数所指对象的引用计数;调用析构函数时,构造函数减少引用计数(如果引用计数减至0,则删除基础对象)。智能指针就是模拟指针动作的类。所有的智能指针都会重载 -> 和 * 操作符。智能指针还有许多其他功能,比较有用的是自动销毁。这主要是利用栈对象的有限作用域以及临时对象(有限作用域实现)析构函数释放内存。

  • 知道B树和B+?说说他们的区别

B树:为了存储设备或者磁盘设计的一种平衡查找树,B+树是B树的一种变形,它把数据存储在叶子节点,内部只存储关键字和孩子指针,简化了内部节点。

B+树遍历高效,将所有叶子节点串联成链表从头到尾遍历。

为什么B+树比B树更加适合做系统的数据库索引和文件索引?

B+树的磁盘读写代价更低,因为B+树内部节点没有指向关键字具体信息的指针,内部节点相对B树小。

因为非终端节点并不是指向文件内容的节点,仅仅是作为叶子节点的关键字索引,因为所有关键字的查询都会走一条从根节点到叶子结点的路径。即所有关键字查询的长度一样,查询效率稳定。

  • 进程间的通信

答出一共有哪几种,优点/缺点是什么,最快又是什么,也可以从一中方式为突破点,从内核角度阐述更为与众不同了!

进程间通信方式描述
管道pipe半双工通信方式,数据单向流动,只能在父子进程中使用。
命名管道FIFO半双工方式是,但是允许非父子关系通信
消息队列大小有限,存放在内核中的链表,建议好好使用ipcs命令。消息队列克服了信号传递信息少、管道只能承载无格式字节流等缺点
共享存储一块内存,多个进程可以访问,共享内存为最快IPC方式。通过和信号量等来解决进程间的同步问题。
信号量计数器,控制多个进程对共享资源的访问,不错的同步手段。
信号通知机制的完美实现,某个进程有事件发生时通知处理即可。
  • 说说系统调用

简单来说是操作系统给我们提供了接口,使用这个接口来和系统进行通信。可以从以下三个方面阐述

1 计算机中的系统态和用户态

应用程序需要调用系统功能时,通过系统调用,CPU转为系统态,取得系统资源,执行系统功能。对应CPU的系统态和用户态,CPU所执行的指令分为特权指令和非特权指令。

  • 系统态:也说是和心态。处理机运行系统的状态

  • 用户态:处理机运用应用程序的状态

2 cpu执行的特权命令和非特权命令

  • 特权命令:

     即CPU在系统态所执行的指令。这种指令只允许系统态的CPU运行,即只允许操作系统调用。特权指令可以对操作系统执行能执行的所有操作,不受任何限制。

  • 非特权:

     即CPU在用户态所执行的指令。这种指令只能执行一般性的操作任务,不能直接进行访问系统中的硬件和软件,其对内存的访问范围也局限于用户空间。应用程序想要访问系统中的硬件和软件,只能通过系统调用间接进行。

  • 项目介绍

老规矩,项目背景,担任什么角色,解决了什么问题,还有什么优化方案等。

二 映客直播面试

因为这个公司基本上都是线下笔试+面试,两天走完流程,如果小伙伴们当地城市有宣讲,可以去尝试尝试的,待遇也还不错!你懂得,姐姐也多!

1 笔试

其中笔试题类似牛客网习题,不过可能还会简单很多,比如进程几个状态呀,画一画状态图呀,mysql优化方式有哪些,b+树和其他树区别(简答题),还有两三个编程题,剑指offer原题。

2 一面(35分钟)

福利态度挺不错的,我记得大厅给我们准备了不少吃的,然后面试过程中还提供饮用水。另外注意了,一面的时候会考察昨天的试卷,而且同样伴随二面,所以第一天没做出来的题目最好回去后查阅下资料吧!

  • 自我介绍

  • 面试官会看昨天的试题,比如笔试题目你做出来了栈实现队列[leetcode栈队列]1 栈实现队列,那么可能会让你写队列转栈。

  • 尽量多的方法实现两个整数的交换(数学方法,介入中间值,位运算)

  • 反转链表(第三次出现)

3 二面

上来先是对一面的总结,然后开始骚操作,一堆逻辑题(就写部分吧,受不了)!

  • 感觉一面如何。

小蓝还是要啰嗦一句,学会覆盘

  • 简历中看你使用过kafka,为什么使用kafka,了解其他消息队列吗,你们项目中的topic多少个,有尝试过优化?

自己看,一口气下来多少个问题,其实你写在简历上面的各个知识点都可以按照这种套路来问你,所以自己做好准备。这也是我们学习一门新的知识非常重要的一环。

暂时先简述消息队列,比如目前的RQ包含了RabbitMQ,ZeroMQ,Redis等,但是kafka天生分布式,高吞吐量,消息可以较长时间持久化,且提供良好的API c接口(因为我当时用的c接口)。其详细总结网上很多,后续自己也会写一份!

  • const 在*左和右的区别,const修饰成员函数有什么作用,如果想修改成员变量,可以将变量修饰成mutable(推荐书籍《c与指针》)

如果const位于星号的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;


如果const位于星号的 右侧,const就是修饰指针本身,即指针本身是常量。


有 const 修饰的成员函数(指 const 放在函数参数表的后面,而不是在函数前面或者参数表内),只能读取数据成员,不能改变数据成员;没有 const 修饰的成员函数,对数据成员则是可读可写的。

  • redis支持哪些数据类型

string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合).当然,最好说说其特点(参考《redis设计与实现》)

  • 来给你写个题目:“请问把一盒蛋糕切成8份,分给8个人,但蛋糕盒里还必须留有一份。大家如何把蛋糕分给这八个人。”

把切成的8份蛋糕先拿出7份分给7人,剩下的1份连蛋糕盒一起分给第8个人

  • 什么是缓存穿透?如何避免?什么是缓存雪崩?何如避免?

缓存穿透

一般来说,缓存系统会通过key去缓存查询,如果不存在对应的value,就应该去后端系统查找(比如DB)。这个时候如果一些恶意的请求到来,就会故意查询不存在的key,当某一时刻的请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透。

如何避免?

  • 对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该key对应的数据insert了之后清理缓存。

  • 对一定不存在的key进行过滤。可以把所有的可能存在的key放到一个大的Bitmap中,查询时通过该bitmap过滤。

缓存雪崩

当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,会给后端系统带来很大压力。导致系统崩溃。

如何避免?

  • 在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。

  • 做二级缓存,A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期。

  • 不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。

4 总结

请记下以下几点:

  • 公司招你去是干活了,不会因为你怎么怎么的而降低对你的要求标准。

  • 工具上面写代码和手撕代码完全不一样。

  • 珍惜每一次面试机会并学会覆盘

  • 对于应届生主要考察的还是计算机基础知识的掌握,项目要求没有那么高,是自己做的就使劲抠细节,做测试,只有这样,才知道会遇到什么问题,遇到什么难点,如何解决的。从而可以侃侃而谈了。

  • 非科班也不要怕,怕了你就输了!一定要多尝试。

暖男告知

跟小蓝每天进步一点点,生活就会美一点!

进入高手如云学习交流群,一起成长!

关注就有内部资源!

往期精彩回顾

[c/c++后台开发面经系列]1 深信服面经

[c/c++后台开发面经系列]2 京东面经(含答案)

写简历这几点一定要注意!

Linux后台开发必看!

今天给二叉树加个BGM,二叉树唱歌了!

在看”的永远18岁~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章