此系列内容以及观点仅个人感受,不妥之处直接私我!目的为了大家能更好的知道面试题难度以及如何准备,希望能让大家少浪费时间寻找资料,多点时间学点干货!因为篇幅原因,大部分题目题解简洁,但有相关资料推荐进阶阅读,学会使用搜索引擎是一门艺术!望谅解!
两个公司岗位都是后台开发工程师,公司共同点都是直播,短视频相关,其面试中问到的题目为常见题目,所以不要怕。bigo四面为电话+视频。映客直播一共三面,但是必须现场笔试,如果通过一面第二天当场面试,嘻嘻,说实话,小姐姐的确多!
一面,二面,三面间隔时间比较长,问题直戳中心(感觉蛮厉害),每轮几乎都有手撕算法,不过可能运气还行,常见题!
自我介绍
主要表明自己姓名,学校,为什么面这个岗位或者公司,具有XX技术,想尝试贵公司等。
析构函数是否可以为虚函数?为什么?
首先,析构函数可以为虚函数,原因:
在实现多态时,当用基类操作派生类,在析构时防止只析构基类而不析构派生类的状况发生。一般情况下,用基类指针指向派生类对象,删除基类指针,这样的删除只能够删除基类对象,而不能删除子类对象,形成了删除一半形象,造成内存泄漏。在公有继承中,基类对派生类及其对象的操作,只能影响到那些从基类继承下来的成员。如果想要用基类对非继承成员进行操作,则要把基类的这个函数定义为虚函数。析构函数自然也应该如此:如果它想析构子类中的重新定义或新的成员及对象,当然也应该声明为虚的.
如果不需要基类对派生类及对象进行操作,则不能定义虚函数,因为这样会增加内存开销.当类里面有定义虚函数的时候,编译器会给类添加一个虚函数表,里面来存放虚函数指针,这样就会增加类的存储空间.所以,只有当一个类被用来作为基类的时候,才把析构函数写成虚函数.
虚函数和纯虚函数的作用和区别
虚函数引入原因:为了方便使用多态特性,我们常常需要在基类中定义虚函数。
纯虚函数引入原因:
1、为了方便使用多态特性。
2、在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出狗子、猫等子类,但动物本身生成对象明显不合常理。纯虚函数就是基类只定义了函数体,没有实现过程(其实可以在类外部实现函数体)。
虚函数和纯虚函数的区别:
带纯虚函数的类叫抽象类,抽象类不能实例化,而能被继承,并重写其纯虚函数后,才能使用。
说说tcp三次握手/四次挥手,加上相关的状态
可以考虑从一次完整的会话来回答,这样思路会更加的清晰。
使用过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 反转链表
编程题2 最大子序和[leetcode数组系列]4 最大子序和
还有什么可以问我的吗?
这个问题一般来说会有下文,只要不问一些敏感话题就行了。
忘记相隔了多少天,某一天晚上一个小姐姐打电话约时间面试。
自我介绍
讲一个你熟悉的项目,当时讲了一个跨网通信程序,引发不少问题出来。(所以,面多了你就知道简历怎么修改,怎么引导面试官问你问题了吧)
遇见过粘包现象吗,如何避免
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 合并有序数组[leetcode数组系列]6 合并两有序数组
因为这个公司基本上都是线下笔试+面试,两天走完流程,如果小伙伴们当地城市有宣讲,可以去尝试尝试的,待遇也还不错!你懂得,姐姐也多!
其中笔试题类似牛客网习题,不过可能还会简单很多,比如进程几个状态呀,画一画状态图呀,mysql优化方式有哪些,b+树和其他树区别(简答题),还有两三个编程题,剑指offer原题。
福利态度挺不错的,我记得大厅给我们准备了不少吃的,然后面试过程中还提供饮用水。另外注意了,一面的时候会考察昨天的试卷,而且同样伴随二面,所以第一天没做出来的题目最好回去后查阅下资料吧!
自我介绍
面试官会看昨天的试题,比如笔试题目你做出来了栈实现队列[leetcode栈队列]1 栈实现队列,那么可能会让你写队列转栈。
尽量多的方法实现两个整数的交换(数学方法,介入中间值,位运算)
反转链表(第三次出现)
上来先是对一面的总结,然后开始骚操作,一堆逻辑题(就写部分吧,受不了)!
感觉一面如何。
小蓝还是要啰嗦一句,学会复盘!
简历中看你使用过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,设置不同的过期时间,让缓存失效的时间点尽量均匀。
编程题:二叉树的层次遍历[leetcode二叉树系列]2 二叉树的层次遍历
还有什么问我的吗?
请记下以下几点:
公司招你去是干活了,不会因为你怎么怎么的而降低对你的要求标准。
工具上面写代码和手撕代码完全不一样。
珍惜每一次面试机会并学会复盘。
对于应届生主要考察的还是计算机基础知识的掌握,项目要求没有那么高,是自己做的就使劲抠细节,做测试,只有这样,才知道会遇到什么问题,遇到什么难点,如何解决的。从而可以侃侃而谈了。
非科班也不要怕,怕了你就输了!一定要多尝试。
暖男告知
跟小蓝每天进步一点点,生活就会美一点!
进入高手如云学习交流群,一起成长!
关注就有内部资源!
▼
往期精彩回顾
▼
[c/c++后台开发面经系列]1 深信服面经
[c/c++后台开发面经系列]2 京东面经(含答案)
写简历这几点一定要注意!
Linux后台开发必看!
今天给二叉树加个BGM,二叉树唱歌了!
“在看”的永远18岁~