查看原文
其他

我被读者卸磨杀驴了......

张小方 高性能服务器开发 2021-05-19

今天晚上正在敲代码的时候,突然收到一条微信消息,消息内容如下:


以上是我收到的消息和我的处理方法。这样的人,我也不想和他有什么过多说法,直接给他全额退款了。

事情是这样的:

这是一位东北某大学的研究生,通过另一位号主的介绍找到我,他想转 C++ 后台开发,希望我能给他一点指导。为了避免重复单次付费咨询,我建议他加入我的知识星球。他加了星球以后,他和我约了一次线上语音交流。

2021 年 5 月 15 日(上周六)我们晚上如约开始了。很多读者可能很好奇,我的知识星球提供的模拟面试到底是怎样的,那么我就以这一次的模拟面试为例来说明吧。

交谈开始后,我先做了一下自我介绍,我叫 XXX,工作 n 年,目前在 XX 公司做 XX 工作(为了对个人信息保密,这里真实信息用 XX 代替,实际交谈的时候说的是真实信息),然后我让他做了下自我介绍,介绍下自己的大学、专业和所学技术栈以及目前的困惑或者诉求。通过他的介绍,我知道了,他是东北某大学某专业研三的学生,非科班出身,喜欢编程,自学 C++ 相关技术栈 2 年,想毕业后去找一份大厂 C++ 后端开发的工作,但是感觉自己目前学的不太好,想让我帮助如何进大厂方面给一些指导。

以上是大致背景。背景介绍完了之后,我说,我先给你做一个模拟面试,你知道多少说多少,之后我会给你总结和建议的。于是正式模拟面试正式开始了。

这里给各位读者一些建议,一般大厂的要求其实总结起来也简单,一句话概括就是:校招看基础,社招看经验。社招比校招难,基础包括算法数据结构、操作系统原理、网络编程、多线程、数据库等方面,对于工作一定年限的社招同学,会进一步问一些软件架构、设计模式、性能调优、分布式、缓存、RPC、消息中间等知识。

既然这位同学是校招,且是非科班出身,我就按校招的要求开始了面试。

我:别紧张,知道多少说多少,咱们正式开始了哈,面试过程中,面试题答案,我不会当场告诉你答案,等下全部结束了,我会给你总结和建议的。

X 同学:好的。

我:既然你想做 C/C++ 后台开发,咱们先从 C++ 编程语言开始吧。

X 同学:好的。

我:C++ 中,A 类有一个 public 实例方法 f,B 类以 protected 方式继承 A,那继承后的 B 的方法 f 的访问权限是什么?

X 同学:应该也是 public 的。

我:你确定吗?有没有实际写过这样的代码。

X 同学:没写过,但应该是 public 的,因为 A 的 f 是 public 的。

我:好的,下一个问题是,一个 A 类除了比 B 类多一个实例方法,其他的方法和成员变量都一模一样,那么 sizeof (A) 与 sizeof(B) 哪个大?为什么?

X 同学:应该一样大,增加一个方法应该不增加对象的大小。

我:为什么?你知道类的方法编译之后如何与类对象关联起来的吗?

X 同学:这个不清楚。

我:那如果 A 类比 B 类多一个 char 型成员变量,sizeof(A) 与 sizeof(B) 哪个大?

X 同学:sizeof(A) 应该比 sizeof(B) 多两个字节。

我:为什么?

X 同学:因为一个 char 类型占 2 个字节。

我:你确定一个 char 类型占两个字节吗?

X 同学:是的。

(谈到这里如果是真实的面试,我可以结束面试了。但是,既然人家付了费,我还是继续下去。)

我:那一个 short 类型占几个字节?

X 同学:2 个字节

我:int 类型呢?

X 同学:4 个字节。

我:那 long 型呢?

X 同学:不太清楚,应该是 8 个字节,不过不太确定。

我:好的,咱们继续哈。C++ 中何为多态?多态是怎么实现的?

X 同学:多态分为静态多态和动态多态,静态多态指的是函数重载,重载指的是继承关系中,子类和父类的函数名一样,但是参数数量和类型不一样;动态多态指的是通过虚函数实现的父子类......(后面具体的我已经记不清了,反正说的不对,原话应该是牛客网上某位同学总结的面经,因为我不止一次听有些同学说过,哎死记硬背的学技术真的害死人)。

(说到了重载,我原来想问两个方法函数名和参数、返回值都一样,但一个带 const 一个不带 const 是否构成重载,但是看这位同学纯粹在背诵性地回答问题,我知道我问了肯定他肯定也回答不出来,算了问个基础的吧。)

我:那如果两个方法,除了返回值不一样,函数名和参数数量和类型都一样,是否构成重载?

X 同学:应该会无法通过编译吧,具体我没试过,不过应该会报错。

我:报错指的无法编译吗?

X 同学:是的。

我:好的。那我们再谈谈你刚才说的动态重载,动态重载一般什么场景下会用到,你能举个例子吗?

X 同学:(把前面背诵的那段动态重载的概念又说了一遍)。

我:那你知道虚表是怎么实现的吗?

X 同学:一个虚表指针,指向类的一个虚表,表格中有很多虚函数指针。

我:好的,你知道常见的函数调用方式有哪些吗?

X 同学:没听说过。

我:那这么说吧,f1(f2(), f3()),实际运行时,先执行 f2 还是 f3?

X 同学:应该是 f3 吧,因为参数的压栈顺序是从右往左的。

我:那有从左往右的吗?

X 同学:不知道。

我:你看过《程序员的自我修养》这本书吗?

X 同学:看过,知乎上有人推荐,但是记不住了。

我:好的,C++ 语言部分咱们就问这么多吧。

(其实,如果基础还可以,我会继续问一些 C++11 的东西,无奈,我知道问了也白问。)

我:我看你简历上写了你熟悉网络这一块,我问几个网络方面的问题吧。

X 同学:好的。

我:你能说一下 TCP 的三次握手过程吗?

X 同学:网络通信发生在客户端和服务端,客户端给服务器端发一个 SYN,序号等于 X,服务端收到回复一个 SYN + ACK,SYN 的序号等于 Y,ACK 的序号等于 X + 1,最后客户端回复 ACK,ACK 的序号等于 Y + 1。

我:那三次握手中客户端和服务端各个状态分别是什么?

X 同学:这个就不知道了。

我:那连接建立成功后,两端处于什么状态?

(不要求你记住每一步的状态,但这里我是期望他能说出是 ESTABLISHED 状态的,然而,我再一次失望了。)

X 同学:这个我不知道。

我:你刚才说的情形是三次握手成功的状态,实际中,我们会遇到一些不成功握手,比如 A 连接 B 一个不存在的端口号,那 A 发送 SYN 之后,B 回复什么?

X 同学:这个我没研究过。

(问到这里,我再一次想结束面试了。无奈,忍着继续。既然他纯靠记忆的,那就问一些可以记忆的网络问题吧。)

我:我们知道理论上的 OSI 网络模型分为七层,你知道这七层分别是什么吗?

X 同学:这个七层我记不清楚了,但是我记得五层。

我:好,那你说说实际实现中有哪五层?

X 同学:应该是物理层、链路层、TCP 层和应用层。

我:还有一层呢?

X 同学:记不清楚了。

我:应该是 IP 层,那你知道 IP 层和 TCP 层哪一层在上面吗?

X 同学:你说的上面是什么意思?

我:就是如果 A 层为 B 层提供服务,B 层就在上面,下层为上层服务嘛。或者你说一个你理解的上层和下层的含义。

X 同学:我理解的越往下就越具体,越往上就越抽象,像电流就是具体的,程序里面的数据就是抽象的。

听他这么说我有点哭笑不得。

我:那你就按你的标准告诉我 TCP/IP 层哪一层更抽象吧。

X 同学:那应该是 IP 层。

(网络编程问到这里,我其实不想问了。再问其他的我估计也不清楚,就从某个面经上背诵了一段三次握手的过程,而且还不加理解,稍微换种方式问(连接不成功的情况)就不知道了。)

我:我看到你项目中还用到了多线程,进程与线程的区别是什么?

X 同学:进程是最小的资源分配单元,线程是最小的调度单位。

我:那一个进程至少得有一个线程,对吗?

X 同学:是的,必须至少有一个线程。

我:那如果一个进程中某个线程挂了,比如内存冲突,会导致整个进程挂掉吗?

X 同学:不会的,不会影响到其他线程,进程仍然可以正常运行。

我:你实际试过吗?

X 同学:我应该没记错。

我:好的,你知道线程之间常用的同步原语有哪些吗?

X 同学:我不知道你说的是什么意思。

我:换个问法哈,比如线程 A 要等线程 B 完成某个工作,才能继续运行,这个要怎么实现?

X 同学:可以使用互斥体。

我:如何使用互斥体?

X 同学:A 线程加锁阻塞在某个互斥体上,B 线程拿到锁,完成工作后解锁。

我:好的,那除了互斥体,有没有更好的方式?

X 同学:可以使用自旋锁。就是 A 一直自旋在某个自旋锁上等 B 完工释放自旋锁。

我:那除了自旋锁,还有其他方式吗?

X 同学:这个就不知道了。

我:那除了互斥体,你还用过哪些锁?

X 同学:还有读写锁、信号量、分布式锁。

(他说到分布式锁,我就哭笑不得了,基础概念已经严重混乱了。)

我:你用过分布式锁吗?什么是分布式锁?

X 同学:这个只在面经上看过,具体没用过。

我:好的,条件变量用过吗?

X 同学:没用过,不熟悉。

我:你再说一下进程之间的通信有哪些方法吧?

X 同学:常见的有管道和油槽。

我:还有其他的吗?

X 同学:其他的就不知道了。

(多线程编程掌握的也不好,基础概念也没搞清楚,再问这方面的东西无意义。)

我:数据库熟悉吗?

X 同学:知道一点。

我:数据库的索引的作用是什么?

X 同学:加快查询速度的。

我:那索引的数据结构是什么?

X 同学:B+ 树。

我:为啥要选用 B+ 树,不能使用其他树吗?比如红黑树?

X 同学:(具体细节我没记不清楚,他的大致意思是使用 B+ 树层级更少,勉强算对吧)

(至此其他的我也不想问啥了,问一下算法和数据结构方面的吧。原来是想问一个快慢链表的问题,不过我估计可能也答不出来。

我又问了一个快速排序、红黑树的定义和哈希表解决冲突的常用方法,除了快速排序,其他的都没答出来。)

面试结束后,我问这位同学如果面试满分 100 分,你觉得你自己能得多少分,这位同学说 20 分,确实是这样,我也只能给他打这么多分。

最后,我又问了他的年龄和想去的城市,他说他 25,想去北上杭广深发展,想去互联网行业。我说互联网行业不一定非要做开发,毕竟你是个女生,产品、测试、运营岗位可能更适合他。他说他喜欢开发,尤其喜欢写 C++,喜欢英文,为了考察一下他的英文,我让他翻译了一个句子:天才是百分之一的灵感和百分之九十九的汗水,他的翻译是:Talent is ninety-nine percent hardwork and one percent idea。翻译的差强人意吧,原话应该是 Genius is one percent inspiration and ninety-nine percent perspiration。

在我挨个解答和点评了一下上面我的问题之后,然后给他挨个讲了一些每个技术栈的学习方法和一些推荐的书籍和资料。

最后,我给出的一些建议:

  1. 一、他的学历不错,但是考虑到还有一个月就要参加校招了,但是连 C++ 基础部分都没掌握好,进大厂可能比较困难,基础部分要补的太多,如果实在想进大厂,还是以算法和数据结构的准备为主吧,尚可一试,不然可能校招连机会都没有;其他部分的知识,先从 C++ 语法开始,建议先找本 C++ 的基础书籍好好看一下,把 C++ 常用语法部分学好,不建议再以《C++ primer》这本书为学习资料了,毕竟太厚了,而时间又这么紧迫,至于其他的基础知识如操作系统原理、网络编程、多线程、数据库等方面建议学有余力再补,但是目前估计来不及了,应该在工作的前几年,把这些基本功和短板补齐。
  2. 二、如果万一进不了大厂,可以退而求其次进一些做 C++ 的小而美的公司,比如各类证券公司、交易所之类的,后面补好技术接着跳。不管怎样,挺好的学历建议第一份工作找个起点相对高一点的平台。
  3. 三、关于工作的选择,城市选择 > 工作类型的选择 > 平台选择(大小厂)> 薪资,比如你想做 C++ 后端,那么某小厂的 C++ 后端开发优于大厂的客户端开发,一份不需要加班加点的工作,月薪少 3k 优于一份要加班加点的工作。
  4. 最后,我给他介绍了一下目前市场对 C++ 开发的需求和方向,别特地强调了一下,C++ 有一个方向是 Windows 桌面软件开发,如果你不感兴趣方向,切记不要选错了。并且给他推荐了一些他可以去试试的公司,最后表示也可以给他内推各家大厂,
  5. 四、最后,也是最关键的一点,如果想做技术开发,不在乎学多少内容,而是学会多少内容,网上的各类面经要在理解的技术上记忆,不要为了面试背诵各种面经;学习技术要从理解其原理的角度来学习,这样才能记得牢,学的好;学习东西除了一些应急的时候之外,建议找一些完整的书籍来系统的学习,相对于其他网络资料,书籍的出版,其流程和审核是很严格的(不要问我怎么知道,这几个月被出版老师折腾的死去活来的),其内容和调理也是有保证的。长期沉迷于面向搜索引擎解决问题,你的知识体系最终会碎片化甚至形成错误的认知和理解。这是他目前最大的问题,以背诵面经的方式来准备面试。

最后,我说,由于我个人经历和经验有限,建议的也不一定对,你可以酌情采纳。然后,就说以后有任何问题或者疑惑还可以约我聊或者在星球提问,然后道了一声“加油”就愉快地结束了对话。

整个过程,七十多分钟,我这边能做的就尽量做了。面试了很多人,有些读者或者面试者基础确实很差,有个人原因,也有环境原因,但是我通常都会委婉的给我的建议,且说出来之前先征求对方意见,如果对方不愿意听,我也不会继续说。

在两天后收到他的这段话,我第一时间觉得很冤枉,接着也不想再搭理这种人了。结果晚上又在微信和知识星球上骚扰我:








推荐阅读
如果你想加入信技术交流群可以先加我微信 easy_coder,备注 加微信群”,我拉你入群,备注不对不加哦。



点赞、在看少个bug

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存