面试 C++ 程序员,什么样的问题是好问题?

来源:互联网 发布:java防止页面脚本注入 编辑:程序博客网 时间:2024/04/19 22:49

原文:https://www.zhihu.com/question/20184857


默认排序

对于应届生:
  • 标准库各容器的基本操作的复杂度。标准库算法的复杂度,例如 std::sort() 的平均复杂度、最坏复杂度(答 O(N^2) 和 O(N log N) 都算对),最坏情况什么时候出现。
  • 标准库各容器(deque 除外)的数据结构(标准党勿喷,主流 STL 实现的数据结构都差不多),以及 vector 的容量增长方式。如果回答得特别好,还可以补充问为什么 vector::push_back() 的复杂度是分摊之后的 O(1),作为加分。
  • 出一道使用 lower_bound / upper_bound 能轻松解决的简单算法题;或者实现 set_intersection() 或 set_union() 或 merge();或者实现 word count,统计每个单词出现的次数(最多十几行代码),如果有时间,输出时再按出现次数排序。
对于社招,补充问:
  • 迭代器失效。(不要求记住所有的场景,但要有这个概念,其实知道数据结构的话不难推理。)
  • 标准库的线程安全性。
  • 自动化对象生命期管理,智能指针,循环引用,weak_ptr。
  • list 的 insert()/erase() 与 vector 相比哪个快。(这个不是那么简单。)

关于什么是好的面试题,多说几句我的看法:

  • 面试官向谁负责。通常应聘者会面试几轮,收集多个面试官的 feedback,交给 hire manager 或 hire committee 决定是否录用。也就是说面试官无权单独决定是否录用这个候选人。在此前提下,面试官的任务是收集足够多的有效信息(包括面试题、答案、答题过程等等),供 hire manager 或 hire committee 决断。因此,面试题要有说服力。应聘者答上了这道面试题,能说明什么,如果没答上来,又能说明什么。不符合这一要求的不是好题目。
  • 难度与区分度。难度定位在“一个合格的 C++ 程序员应该掌握的基本知识”,是招能用 C++ 干活的人,不是招标准控或语言律师。所有人都能做出来和所有人都做不出来的题目,没有区分度,不是好题目。所有应聘者都能通过或者所有应聘者都被刷掉的面试官也不是好面试官。
  • 公平性与可重复性。技术面试题应该有比较公认的正确答案,怎么样算答得好,不仅由面试官一个人做出判断,hire manager 和 hire committee 也能重复这一判断。一套好题目,能起到筛选多个面试者的作用,比如“眼前这个应聘者的回答与过去六个月里的应聘者相比,处于前 10 % 的位置”,这就是不错的客观标杆。
编辑于 2014-04-17

不敢妄言什么是“好问题”,仅仅只是说说我喜欢问什么样的问题。

我在面试的时候主要考查面试者分析问题和解决问题的能力,因此我会给出一个实际工作中会遇到的问题,让面试者分析问题,给出解决方案,最后用具体的代码实现这个方案。解决这个问题需要的知识点都非常非常基本,绝对不会超过《数据结构与算法》这门课能够覆盖的内容。换句话说,也就是计算机相关专业的第二学期专业课就能够涉及到的内容,仅此而已,并非很多人宣称的必须精通 ACM,精通《算法导论》那么恐怖。

在面试过程中,最重要的就是分析问题和解决问题。一个应聘者如果仅仅满足于背课本做习题的话,遇到实际工作中的问题往往不知道如何把课本上的知识用上去,因此光死读书,平时不实践是不行的。至于花时间去阅读什么“面试宝典”、“脑筋急转弯”什么的,就更是没有意义了。很多网上广为流传的“判断单链表是否有环”啊,“不开辟额外空间把数组前 n 个元素移动到尾部”啊之类的题目,本质上和脑筋急转弯并没有区别,这种题目并不能考查出面试者分析问题和解决问题的能力,在实际面试中也是不会用的。

总之,只要基础知识掌握足够牢靠,再加上平时足够的实践,通过面试就完全没问题了。事实上,我遇到过有一个应聘者 fopen 不会用,memcpy 的调用方法也记错了,但这些都不是问题,由于他分析问题思路完全正确,写代码的时候格式规范,条理清晰,因此最后也毫无悬念地通过了面试。

至于模板、容器、虚表、多继承等 C++ 语言细节,正常情况下我是不会在面试里考查的,除非一个应聘者表现极其好,为了让他能够再得到一些额外的加分,我会故意问一些琐碎的语言细节,好让他有机会表现一下。如果他答上来了,我就在评语里再表扬他几句;如果没答上来,那就算了,无妨。
编辑于 2013-08-28
学习C++:实践者的方法
看完这个楼主或许会知道应该提问那些重点
发布于 2014-04-17
微信二维码
我认为有一个好问题适合面试所有的程序员,那就是拿出一份三千行以上的代码,给他半小时的阅读时间,然后提出这些问题:
1,这份代码是不是商用代码/适不适合商用
2,这份代码的缺陷是哪些
3,这份代码有哪些不规范的地方
4,指出代码的分层
编辑于 2014-04-17
微信二维码

我做面试官也有一段时间了,遇到过形形色色的C++程序员,水平参差不齐。这里说一下我的经验吧:

我最常问的问题是,用C++写一个有理数类,class Rational,实现基本的加减乘除和输入输出操作。
别看这么小小的一个问题,居然可以考察到非常之多的地方,犹如闯关游戏一般,直到把这个面试者推向极限。

  1. 完全不知所云的,甚至有说忘了有理数是啥的,我就耐心地告诉他,两个整数之比定义为有理数,第一个叫做分子,第二个叫做分母。然后礼貌地结束面试。
  2. 如果搞不清楚的怎么做的,我会给一个main函数的示例(见下面的代码),告诉他“面向接口编程,不要面向实现编程”。我发现有经验的人,会问我接口或者对象的行为是什么样的。
  3. 能搞清楚问题,首先让他写出类的声明,然后就可以问,哪些是public,哪些是private的,什么是运算符重载。为何传递参数要写 const Rational&。
  4. 继续问,构造函数,析构函数,拷贝构造函数,operator= 是怎么回事,相关知识云云,构造函数是不是前面要加 explicit 修饰。
  5. 继续问 istream和ostream的重载怎么写,friend 函数是怎么回事。
  6. 让面试者写代码,尽可能完整地实现这个类的成员函数,中间观察编程习惯,代码风格等等
  7. 有理数分母不能为0,看看面试者是不是够仔细,还有对C++的异常控制是否有了解。包括数字过大的时候,整数溢出了是否有考虑。
  8. 1/3+1/3+1/3输出应该是1,所以分子分母要约分,求最大公约数这个点想到。如果有负数,最大公约数怎么求?
  9. istream输入的情况可能会很多,涉及到字符串的解析,"3.5","1/3", "-1/5", "-0.3",看看面试者能正确处理多少种情况?顺便问一下测试方面的问题。
  10. 有理数的分子分母可能会很大,是不是可以考虑模板化,写成Rational<T>,然后可以有个Bigint的类来实现 typedef Rational<Bigint> HighPrecisionRational;
//我期望看到的解答#include <iostream>class Rational{public:    Rational();    Rational(int x);    Rational(int x, int y);    Rational(const Rational& r);    const Rational& operator=(int x);    const Rational& operator=(const Rational& r);    virtual ~Rational();    bool operator== (const Rational& other) const;    friend const Rational operator+ (const Rational& r1,                                      const Rational& r2);    friend const Rational operator- (const Rational& r1,                                      const Rational& r2);    friend const Rational operator* (const Rational& r1,                                      const Rational& r2);    friend const Rational operator/ (const Rational& r1,                                      const Rational& r2);    friend std::ostream& operator<< (std::ostream&, const Rational& r);    friend std::istream& operator>> (std::istream&, Rational& r);private:    static int gcd(int p, int q);    int num; //numerator    int div; //divisor};int main(int argc, char* argv[]){    Rational a(1, 3); //a等于三分之一    Rational b = 3; //b等于3,3也是有理数    b = a;    Rational c(a+b+Rational(1,3)); //有理数可以做加法    std::cout << "a=" << a << std::endl;    std::cout << "b=" << b << std::endl;    std::cout << "c=" << c << std::endl; //输出结果    std::cout << "Please input a Rational number like 13/15" << std::endl;    Rational d;    std::cin >> d;    std::cout << "value d+1=" << d+1 << std::endl;    return 0;}//gcc -g -O0 -o rational Rational.cpp -lstdc++

面试者能闯到最后一关的,我已经比较满意了。整个面试的过程中围绕着一个功能的实现反复交流和改进,我们的谈话已经涉及到了C++、字符串、算法、数学、代码风格、软件工程、测试的很多方面的知识了;同时对面试者的表达能力,沟通能力,性格方面也有所了解了。

finally. 我会给一个杀手级问题,这里分子分母约分用到了gcd,请问时间复杂度是多少?啊哈,这里要请出Knuth爷爷的《计算机程序设计艺术》啦!wow!

========================华丽的分割线========================
非常感谢 @时习之 的建议。我补充说明一下
1. 确实如他所说的,先给出operator+=,然后再去实现非友元的operator+,这样是能减少代码冗余的;如果只是要求实现加减乘除操作,用友元operator也没有问题。
2. 如果只是考虑在控制台输入输出,iostream就能满足需求了; 如果更往深了讨论,比如涉及到字符串解析(sstream),文件的读写(fstream),这个时候就需要重载参数为basic_stream
Template<typename charT>basic_stream<charT>& operator<< (basic_stream<charT>& os, const Rational& r);Template<typename charT>basic_stream<charT>& operator>> (basic_stream<charT>& os, const Rational& r);

3. std::complex是复数,而Rational是有理数,实现细节上还是多有不同的。如果是要求面试者实现一个complex的话,我曾要求他实现出复数的乘方和开方运算。
4. operator= 应该返回 const Rational&,已改正;
5. 为何不直接用系统默认合成的构造析构函数。Rational x; 的值是多少呢?我的习惯是初始化为0,而且不希望分母为0
6. 构造函数Rational::Rational(int x),我认为是不应该声明为explicit的,因为我希望重载了operator+运算符之后,r+1, 1+r都能work。

我们这里并不是要求应聘者是一名C++语法专家,更多的是希望在相互讨论的过程中,观察面试者思考问题的深度和全面性,以及应变能力。
编辑于 2016-04-10

转帖一下我在其他问题里的答案

------------------------
实际的面试中,一般按照以下的标准来区分水平。(随便写的,不成系统)
1 听说过C++
常见的问题 什么是类,什么继承
new和malloc有什么区别
什么是虚函数,什么是虚继承
之类的泛泛而谈的入门问题
2 会C++
new实际上执行了什么操作,可能在什么步骤出现异常
怎么写一个class,禁止分配在栈上
怎么突破private的限制访问变量
虚继承的细节
怎么自己模拟实现引用
3 比较了解C++
主要是一些边角的语法或者是不常见的问题
逗号表达式,位域
初始化列表的异常怎么捕获
对于常见的主流编译器,写不写inline有什么影响
完美转发
怎么在编译器判断一个类中有没有定义某个特定的方法
构造函数中调析构函数会有什么结果
发布于 2015-02-27
我一般会循序渐进的问问题,以C++的虚函数为例。
  1. 了解多态么?它是怎么实现的?什么时候应该使用它?
  2. 在语言层面,虚函数是怎样实现的?为什么还要区分虚函数和普通函数,都成虚函数不好么?
  3. 虚表里存储的是什么?
  4. 如果基类定义先声明了f函数后声明了g函数,子类定义会反过来(真正面试的时候会有样例代码给出),那么虚表里第一项是什么?
  5. 如果有多继承,虚表内会怎样?
  6. 等等。。。
这只是个大体思路,关键是看求职者的现场反应能力和链接能力,比如:
  • 第一题,如果提到静态多态,并且简单询问后确认懂得什么是静态多态则有额外加分。
  • 第二题,提到和其他语言的对比(如java oc python 等),有额外加分。
  • 第四题,关键不在于答案,而在于回答的思路。如果在回答出大体原理之后加以说明这东西是undefined,不应该依赖于这个结果,有额外加分。
  • 第五题,如果一开始求职者不太了解这个事情,但是通过我简单的提示,能够沿着这个思路走下去,无论对错,均有额外加分。

如果在面试中会询问到了求职者之前没有思考过的问题,我会给出适当的提示,逼迫其现场思考。

如果中间被求职者带跑了,比如问第一题的时候扯到模板元编程了,我的态度就是随着他跑,在他自己最擅长的领域才能看出他的思路究竟是怎样的。

总之,尽量通过方方面面探知求职人员对技术核心思想的把握能力,如果在面试之前他就考虑的很透彻,这是上上之选(原因是其会自己沿着正确的方向独立思考),如果在面试中可以现场考虑出大概,这是上之选(原因是其逻辑思维还不错)。

思维方式很重要,某种程度上,这东西决定一个人的命运。
发布于 2014-05-23
如果是老鸟,我会问:如果有一个准备学习C++的学生让你推荐书籍,你会给出哪些书单?
如果是菜鸟,我会选择一些操作系统、数据结构的知识,再搭载一些STL分析。
编辑于 2015-09-20
我推荐一个吧,相比C++语法和标准库,我个人更加喜欢这个问题,这也是当时经理面试我的唯一问题:"谈一谈在你眼中的C++哲学和思想”,这个问题我觉得可以看出他对C++的喜爱程度、研究程序,这远远比那些利用手册可以查到的语法更加重要。只有去探讨了C++的哲学与思想,他才知道C++到底为什么是这样,才会去更加明白何时、何地、如何地利用C++,当然也更加能确定他是否喜爱上了C++(甚至抱有着一种信仰),只有爱上了一个东西,他才会更加对他写的C++代码负责,也许这有点儿所谓的宗教色彩,但是有时候只有这种宗教般的信仰,才能让他更加的执着。这样的C++程序员,我想远比记忆了语法的C++程序员更加难得与弥足珍贵。
发布于 2014-04-15
有女朋友吗?
发布于 2014-04-18
静态局部变量存放在哪里?它的地址在什么编译时还是运行时确定的?
发布于 2015-04-06
最新的几个标准的大致内容,及其个人点评
发布于 2014-04-15
几个思路吧
1. 入门问题,基本的数学素养和逻辑分析,C++语言的语法、重要的数据结构和算法思路,鉴别面试者的基本功。
2. C++11的新特性,以及对这些特性的看法?或者,你看的C++的著作,看看是否是一个学习型的程序员。
3.进阶一点的话题,例如容器、模版、面向对象、SEH等,看面试者的知识面和功底。
4.实战,你以前碰到的最莫名其妙的bug,以及如何解决的?看面试者的综合经验和能力
发布于 2016-03-02
微信二维码
斯特朗斯特拉普的《c++程序设计语言》中不太难的练习题。
发布于 2014-08-20
tilaile.com刷题吧,一堆一堆的,都有答案…
发布于 2016-02-24
作为一个面试者,能力有限,只能说别问那些网上一抓一大把的死问题
如:实现一个string类,实现一个链表,socket套接字,类似GetMerory函数的改错题…
每次看到这些我就想吐了,这些问题作为应届生题目还好…我面试的都是两年以上工作经验的…不知道是他们懒还是能力有限
上次有一家公司就出的不错,让你现场用vs2008实现一个一个功能,可以上网查资料…谁都有遇到问题的时候,关建是看你解决问题的能力
发布于 2014-04-16
去nowcoder上看吧,C++题目一把一把的
发布于 2015-07-10
微信二维码

问一些C++比较隐蔽的问题。

如果他知道答案,会接着问原理。

如果不知道答案,这样更好,我就会问如果你是设计者,你会如何解决问题,如果他能自圆其说,说明逻辑思维很好。

发布于 2017-05-08
1. 模板方法(template method)设计模式
2.介绍面向过程、基于对象、面向对象、面向接口编程。
发布于 2016-03-03
给个错误给他调试!
发布于 2014-07-03
微信二维码
我遇到过的最好的面试方法就是 直接给你一个需求,让你在一定时间内完成。
发布于 2014-04-17
熟练掌握一门语言只需要回答两个问题
1这门语言的局限处
2对这门语言未来发展的解读
发布于 2015-07-10

私以为 面试时问一些问题是必要的 但是专业skill你确还是不会知道 因此 在国外类似于google 'IBM 微软等公司想要招聘理想程序员时 他们会通过topcoder等在线编程比赛 来聘用第一或者第二

因此 在国内 我觉得也应该有这样一些 软件 用于在线编程 但我所知现在国内有的 也只有猿圈
发布于 2015-04-15
必然是数据结构,或者或者C++特性容器之类的啊,模版的就不用了吧,那些东西提高效率工具的而已,基础才是王道。或者你就从Primer和effective C++上找一些常识性的,如果常识的都不能弄熟,深入的就免谈了,换句话说,如果常识性的搞的很透而且有自己的一些补充见解,说明此人很认真,很注重细节,很有想法,即使深入的问题不是很熟练,这样人也比招个纯码农要好得多。
发布于 2012-04-18
“你觉得C++不好的地方在哪里?你会如何改善?”
发布于 2014-04-15
假定一个类的构造函数为A(int aa,int bb){a=aa--;b=a*bb;},则执行A x(4,5);语句后,x.a和x.b的值分别为()
  • 20和5
  • 3和15
  • 5和4
  • 4和20
发布于 2016-03-04
可以问问 epoll select 等等~~~
发布于 2016-03-02
你还准备在这个坑中呆多久?
发布于 2014-05-30



原创粉丝点击