时间线

流程概况

240221 牛客简历初筛

…挺快,几个小时后就收到了面试邀约。

240223 一面口头过

主要聊了 C++,写了两道题。最后出了点问题,但在最后改对了(还是太紧张了),但还是给我过了。差强人意吧。

240304 感谢信

一面口头过了,但估计还因为大二以及实习只有两个月,以及面试表现不算特别突出,最后正式挂了。

一面

面试过程

首先是相互介绍,面试官先介绍了它们部门的业务,然后我介绍了一下我的技能项。

问题 解答情况
(面试官自我介绍,我的自我介绍)
什么时候开始打 ACM?高中有没有代码基础? balabala,如实回答。
LRU-K 是啥?我知道 LRU,你给我大概讲讲 LRU-K。(面试官读简历中…) balabala,面试官应该是真不知道。
Copy-on-Write 又是什么东西?(面试官读简历中…) balabala,面试官应该是真不知道。
(后面开始问 C++)
总结下 static 这个关键字。 函数中的 static,类中的 static,总之可以扩大生命周期。
追问: static 成员函数是否可以访问普通成员变量? 答不能,然后扯一大堆。面试官应该期望可以通过某种方式能。
总结下 const 这个关键字。 常量,const 成员函数,constexpr。这边有一部分答上来但是觉得不够完美。
追问: const 成员函数的本质是什么? 在面试官一些提示下才答上来,见梳理。
追问: 再想想 const 还有其他方面吗? 我提了 const & 的参数可以接受右值,应该是还有,见梳理。
RTTI 是什么东西? balabala,面试官居然不懂 RTTI
STL 里是怎么进行底层内存分配的? allocator,然后讲它是干嘛的?
追问: 是否了解它的算法? 不了解 allocator 的实现,但清楚 STL 的实现。
追问: 讲一下 vector 的底层实现。 balabala,这个太轻松了。
追问: vector 什么时候会迭代器失效。 先犹豫了,说不知道 push_back 会不会失效。然后回忆之前遇到过迭代器失效,说 push_back 扩容时会导致迭代器失效,然后说 insert 会导致向后的迭代器失效。
智能指针的实现原理是什么? 主要是 shared_ptrunique_ptr,然后我讲了一下 shared_ptr 源码是怎么做的。
追问: 循环引用怎么解决? 那就是 weak_ptr,然后讲了 shared_ptr 的引用计数由 shared 计数和 weak 计数组成。
追问: shared_ptr 有几种构造方式? shared_ptr 传入指针构造,make_shared 会将参数传入内部构造。
追问: 这两者有什么性能或者安全方面的区别。 只回答了性能方面的区别。效率方面,make_shared 可能传入内部构造,可能带来性能上的提升,但我不清楚具体有什么样的提升。(性能方面不算回答的好,安全方面复盘才听到面试官提了安全)
(最后我们做两道题目)
带有过期标记的 LRU 讲解过程遇到了问题,面试官直到先从数据结构开始讲。
bitmap(手搓 bitset) 在计算值遇到了问题,出锅严重,被狠批。。。好在前面回答的都不错。

面试官主要和我聊了 C++,其中还是以 C Class STL 为多(除了 allocatorshared_ptr)。聊起 C++ 感觉面试官还不如我懂(比如 RTTI),但是它问的也有我答不上来的。

梳理没答上的问题

static 成员函数是否可以访问普通成员变量?

不能直接访问。

为什么不能? 这个问题我回答的很好,扯了一大堆。唯一的缺点是没法简短概括。

为什么能? 通过传入一个 this 指针就可以了。然后可以扯一下这其实就是类函数调用的原理,面试官应该就是想要这句话。

关于这个问题虽然我没有打上第二点,但是在讲到 const 的时候,在面试官追问下还是答上了调用原理。

const 这个成员的应用?

一个让面试官有疑惑的回答 当时我说了 const 变量是能用 const 就用 const,没解释清楚(其实就是想说给用户最小的权限),面试官 “啊?” 了一下,但是后面没追问,当时这个地方回答应该算让面试官疑惑,不如不说后半点。

const 成员函数的本质是在修饰什么? 这里直接上问答吧:

面试官:const 成员函数的本质是在修饰什么?

我:(一脸疑惑)应该是在修饰变量的每个成员吧。

面试官:那我换个问法,const 成员函数和普通成员函数是不是重载关系?

我:是的。(然后嘶… 了一会儿)我不知道是不是你想要的回答,const 成员函数本质是传入了一个 const 的 this 指针。

面试官:是的,这是我要的答案。

(感觉还可以扯一下,const * 和 * 是重载关系,* const 和 * 不是重载关系)

const 的应用还有其他什么方面?

  • 我提到 const & 的参数,可以接受右值引用、字面值,然后还有一些方面在面试官追问下完成。
  • 追问:const 作为函数的返回值?答:const 的返回值没有意义,但是 const & 的返回值可以减少拷贝或者移动。(这个问题我想了一段时间,还可以补充 const & 的返回值需要注意这个值不能是函数内的变量)
  • 追问:const 常量与 #define 一个常量比有什么好处?答得不好,但面试官没说什么。应该的回答:类型安全、具有作用域、避免其他奇怪错误,然后可以回答 #define 是在预处理期完成的。

智能指针相关内容

weak_ptr 为什么需要 weak 计数 这是一个我假想的问题,当时回答 weak_ptr 的时候其实心虚面试官万一追问这个问题怎么办,不过最后没有追问。weak 计数其实不是需要被使用,而是代码实现上不这么做就会出现问题。在没有 weak_ptr 时,shared_ptr 在引用计数为零时会卸载对象和计数器;而在有 weak_ptr 时,shared 计数为零时只能卸载对象,而计数器需要在 weak 计数为零时卸载计数器,如果不这么做,那么 shared_ptr 直接卸载计数器,weak_ptr 的计数器指针就会出现指针悬挂。

shared_ptr 和 make_shared 的性能差异到底体现在哪里? make_shared 一次申请计数器和对象的总内存,然后进行构造。而 shared_ptr 则是分别申请计数器和对象的内存的。但 make_shared 也有不好的地方,weak_ptr 可以使计数器存活,而对象被释放;但在 make_shared 中,计数器和对象必须同时卸载。

make_shared 比 shared_ptr 更加安全。 在使用 shared_ptr 作为参数传入时,它的构造顺序允许被编译器打乱,如果使用临时构造的对象传入 shared_ptr 就会存在安全问题。另外 make_shared 一次分配内存也会比多次分配更加安全。

面试总结

这场面试主要考察了 C++,但是出乎意料的是,这位面试官更加注重相关基础方面的,比如 static / const 的内容居多。

其中,关于 const 作返回值和 const#define 的区别回答的不到位,中间花在思考上的时间比较多,就是还做不到应对自如。然后是 shared_ptr 方面没有答出 make_shared 的具体优势,只回答了潜在优势。

面试官最后总结到,你的 C++ 还有需要巩固的地方,因为我们的岗位是 C++ 的,所以后期还要多准备。其实当时还觉得我对 C++ 的内容都算回答出来了,但是需要面试官一些提示,但是现在复盘了一下感觉比当时感觉的不足还是要多一些的。

最后笔试题出锅的事暂时就放一边了。面试官提到我 “小动作太多”,还说我面试的时候头甩来甩去,这个需要改正。当时想确实有问题,不过事后想想写题过程中,还有一个细思极恐小故事:

在我 LRU 快写完的时候,面试官发消息(不是口头)说去上个厕所,我到感觉压力小了点,写题反而更加轻松了。不过心里还是有点这样的想法:这个面试官怎么这样…

现在想想面试官大概率是有意不是无心。

最后面试官回复我这里算是给你过了。

感谢信

估计大二以及实习时间短占主要原因。

另外,对基本 C++ 问题的掌握有待提高,在面试中训练吧。