面试 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 % 的位置”,这就是不错的客观标杆。
不敢妄言什么是“好问题”,仅仅只是说说我喜欢问什么样的问题。
我在面试的时候主要考查面试者分析问题和解决问题的能力,因此我会给出一个实际工作中会遇到的问题,让面试者分析问题,给出解决方案,最后用具体的代码实现这个方案。解决这个问题需要的知识点都非常非常基本,绝对不会超过《数据结构与算法》这门课能够覆盖的内容。换句话说,也就是计算机相关专业的第二学期专业课就能够涉及到的内容,仅此而已,并非很多人宣称的必须精通 ACM,精通《算法导论》那么恐怖。
在面试过程中,最重要的就是分析问题和解决问题。一个应聘者如果仅仅满足于背课本做习题的话,遇到实际工作中的问题往往不知道如何把课本上的知识用上去,因此光死读书,平时不实践是不行的。至于花时间去阅读什么“面试宝典”、“脑筋急转弯”什么的,就更是没有意义了。很多网上广为流传的“判断单链表是否有环”啊,“不开辟额外空间把数组前 n 个元素移动到尾部”啊之类的题目,本质上和脑筋急转弯并没有区别,这种题目并不能考查出面试者分析问题和解决问题的能力,在实际面试中也是不会用的。
总之,只要基础知识掌握足够牢靠,再加上平时足够的实践,通过面试就完全没问题了。事实上,我遇到过有一个应聘者 fopen 不会用,memcpy 的调用方法也记错了,但这些都不是问题,由于他分析问题思路完全正确,写代码的时候格式规范,条理清晰,因此最后也毫无悬念地通过了面试。
至于模板、容器、虚表、多继承等 C++ 语言细节,正常情况下我是不会在面试里考查的,除非一个应聘者表现极其好,为了让他能够再得到一些额外的加分,我会故意问一些琐碎的语言细节,好让他有机会表现一下。如果他答上来了,我就在评语里再表扬他几句;如果没答上来,那就算了,无妨。看完这个楼主或许会知道应该提问那些重点
1,这份代码是不是商用代码/适不适合商用
2,这份代码的缺陷是哪些
3,这份代码有哪些不规范的地方
4,指出代码的分层
我做面试官也有一段时间了,遇到过形形色色的C++程序员,水平参差不齐。这里说一下我的经验吧:
我最常问的问题是,用C++写一个有理数类,class Rational,实现基本的加减乘除和输入输出操作。
别看这么小小的一个问题,居然可以考察到非常之多的地方,犹如闯关游戏一般,直到把这个面试者推向极限。
- 完全不知所云的,甚至有说忘了有理数是啥的,我就耐心地告诉他,两个整数之比定义为有理数,第一个叫做分子,第二个叫做分母。然后礼貌地结束面试。
- 如果搞不清楚的怎么做的,我会给一个main函数的示例(见下面的代码),告诉他“面向接口编程,不要面向实现编程”。我发现有经验的人,会问我接口或者对象的行为是什么样的。
- 能搞清楚问题,首先让他写出类的声明,然后就可以问,哪些是public,哪些是private的,什么是运算符重载。为何传递参数要写 const Rational&。
- 继续问,构造函数,析构函数,拷贝构造函数,operator= 是怎么回事,相关知识云云,构造函数是不是前面要加 explicit 修饰。
- 继续问 istream和ostream的重载怎么写,friend 函数是怎么回事。
- 让面试者写代码,尽可能完整地实现这个类的成员函数,中间观察编程习惯,代码风格等等
- 有理数分母不能为0,看看面试者是不是够仔细,还有对C++的异常控制是否有了解。包括数字过大的时候,整数溢出了是否有考虑。
- 1/3+1/3+1/3输出应该是1,所以分子分母要约分,求最大公约数这个点想到。如果有负数,最大公约数怎么求?
- istream输入的情况可能会很多,涉及到字符串的解析,"3.5","1/3", "-1/5", "-0.3",看看面试者能正确处理多少种情况?顺便问一下测试方面的问题。
- 有理数的分子分母可能会很大,是不是可以考虑模板化,写成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。
转帖一下我在其他问题里的答案
------------------------实际的面试中,一般按照以下的标准来区分水平。(随便写的,不成系统)
1 听说过C++
常见的问题 什么是类,什么继承
new和malloc有什么区别
什么是虚函数,什么是虚继承
之类的泛泛而谈的入门问题
2 会C++
new实际上执行了什么操作,可能在什么步骤出现异常
怎么写一个class,禁止分配在栈上
怎么突破private的限制访问变量
虚继承的细节
怎么自己模拟实现引用
3 比较了解C++
主要是一些边角的语法或者是不常见的问题
逗号表达式,位域
初始化列表的异常怎么捕获
对于常见的主流编译器,写不写inline有什么影响
完美转发
怎么在编译器判断一个类中有没有定义某个特定的方法
构造函数中调析构函数会有什么结果
- 了解多态么?它是怎么实现的?什么时候应该使用它?
- 在语言层面,虚函数是怎样实现的?为什么还要区分虚函数和普通函数,都成虚函数不好么?
- 虚表里存储的是什么?
- 如果基类定义先声明了f函数后声明了g函数,子类定义会反过来(真正面试的时候会有样例代码给出),那么虚表里第一项是什么?
- 如果有多继承,虚表内会怎样?
- 等等。。。
- 第一题,如果提到静态多态,并且简单询问后确认懂得什么是静态多态,则有额外加分。
- 第二题,提到和其他语言的对比(如java oc python 等),有额外加分。
- 第四题,关键不在于答案,而在于回答的思路。如果在回答出大体原理之后加以说明这东西是undefined,不应该依赖于这个结果,有额外加分。
- 第五题,如果一开始求职者不太了解这个事情,但是通过我简单的提示,能够沿着这个思路走下去,无论对错,均有额外加分。
如果在面试中会询问到了求职者之前没有思考过的问题,我会给出适当的提示,逼迫其现场思考。
如果中间被求职者带跑了,比如问第一题的时候扯到模板元编程了,我的态度就是随着他跑,在他自己最擅长的领域才能看出他的思路究竟是怎样的。
总之,尽量通过方方面面探知求职人员对技术核心思想的把握能力,如果在面试之前他就考虑的很透彻,这是上上之选(原因是其会自己沿着正确的方向独立思考),如果在面试中可以现场考虑出大概,这是上之选(原因是其逻辑思维还不错)。
思维方式很重要,某种程度上,这东西决定一个人的命运。如果是菜鸟,我会选择一些操作系统、数据结构的知识,再搭载一些STL分析。
1. 入门问题,基本的数学素养和逻辑分析,C++语言的语法、重要的数据结构和算法思路,鉴别面试者的基本功。
2. C++11的新特性,以及对这些特性的看法?或者,你看的C++的著作,看看是否是一个学习型的程序员。
3.进阶一点的话题,例如容器、模版、面向对象、SEH等,看面试者的知识面和功底。
4.实战,你以前碰到的最莫名其妙的bug,以及如何解决的?看面试者的综合经验和能力
如:实现一个string类,实现一个链表,socket套接字,类似GetMerory函数的改错题…
每次看到这些我就想吐了,这些问题作为应届生题目还好…我面试的都是两年以上工作经验的…不知道是他们懒还是能力有限
上次有一家公司就出的不错,让你现场用vs2008实现一个一个功能,可以上网查资料…谁都有遇到问题的时候,关建是看你解决问题的能力
问一些C++比较隐蔽的问题。
如果他知道答案,会接着问原理。
如果不知道答案,这样更好,我就会问如果你是设计者,你会如何解决问题,如果他能自圆其说,说明逻辑思维很好。
2.介绍面向过程、基于对象、面向对象、面向接口编程。
1这门语言的局限处
2对这门语言未来发展的解读
私以为 面试时问一些问题是必要的 但是专业skill你确还是不会知道 因此 在国外类似于google 'IBM 微软等公司想要招聘理想程序员时 他们会通过topcoder等在线编程比赛 来聘用第一或者第二
因此 在国内 我觉得也应该有这样一些 软件 用于在线编程 但我所知现在国内有的 也只有猿圈- 20和5
- 3和15
- 5和4
- 4和20
- 面试 C++ 程序员,什么样的问题是好问题?
- 面试 C++ 程序员,什么样的问题是好问题?
- 好的程序员什么样?
- 什么样的公司程序员待遇好?
- 什么样的公司程序员待遇好
- 面试官更喜欢什么样的Java程序员
- 什么样的电脑好
- 数据量的问题是很多面试笔试中经常出现的问题
- 什么样的程序员最易涨薪?
- 什么样的程序员最易涨薪?
- 一个公司的C/C++程序员面试问题
- 程序员应对面试的好东西
- 程序员如何写好简历 && 一份优秀的程序员简历是什么样的?
- 信息安全问题是互联网的首要问题.
- 焦虑和年龄的问题是问题吗
- 好游戏是什么样的
- 好文章是什么样的
- 面试官的犀利问题是为了知道这些
- Linux系统编程与网络编程
- Linux:重定向(redirect)
- 数据结构基础学习笔记 part 2
- eclipse使用github实现版本控制,轻松解决代码管理问题
- 25779.html
- 面试 C++ 程序员,什么样的问题是好问题?
- JAVA只有值传递
- ASP.NET 控件开发基础
- js事件模型
- Kruskal算法(贪心+并查集=最小生成树)
- C/C++结构体语法总结
- python~module gzip 使用方法,及简介! 附件 python ~ os 模块!!!
- 就是要你懂 TCP
- Spring导出PDF