之前秋招完成了福富软件的面试题,30分钟42道选择题,时间看来相对新大陆还是比较紧的,一些出现失误或卡壳的题目知识点做个总结。
1.假设MyClass为一个类,则执行"MyClass a(2),b[5],*c[4];"后,构造函数执行几次?
答:6次,这里a(2).b[5]属于在栈空间内分配内存,*c[4]是4个MyClass类的指针,指针没有初始化时(没new时)不调用构造函数,笔者在这稍微卡了半分钟。
2.如果有如下语句:char str[20]; cin>>str;cout <<str;输入this is a test line!时,输出是?
答:this,这里有陷阱,空格后面的字符cout不出来,this后面有一个空格,所以打印不出来空格后面的字符。
3.已知一个类X,( )是定义指向类X成员函数的指针,假设类有3个公共成员:
void f1(int),void f2(int)和int a.
A.X* P B.int X::*pc=&X::a C.void(X::*pa)() D.X* p[10]
这题出的比较新,笔者的项目过程很少通过这种方式来获取类间函数的地址,但是用排除法一般可以出结果的,AD是可以先排除的,因为它们只是声明了一个指向类的指针而已,B的话指向的是类里面的一个变量名,不是指向一个函数名,因此这题应该是选C,但其实执行下来并没有什么结果,f1和f2也不太清楚放这里干什么用的。
4.考了关于静态联编、动态联编、动态加载的问题,具体问题好像是:( )要求在运行时解决程序中函数调用与函数执行……
静态联编又叫静态绑定,指的是在调用同名函数时实参在编译时就根据参数确定了要调用哪个函数,优点是速度快效率高,但灵活性不够。
动态联编又叫动态绑定,指的是在程序运行时,根据当时的情况来决定那个调用的同名函数的实现
像虚函数就是典型的动态联编,因为在运行时才从虚表中找到函数的入口地址。
动态加载则是在执行时导入动态库内的某个函数。
5.关于模板函数和函数模板的区别:函数模板是含泛型的一个函数体,而模板函数则是当已经知道泛型类型时,将其带入产生的模板函数。
6.还有一题的答案比较有争议,写出下列程序的输出:
int a = 2, b = 3, c = 4;
a += b *= (++b - c++);
cout << a;
cout << b;
cout << c;
这个后面我用编译器纠正了一下都是输出205 不知道为啥考试中的选择题没有那个选项,非常奇怪。
7.构造函数不可作为虚函数,这个在睿能的面试题中已经出现一次了,再做一个记录加深印象。
===================面试过程答不好的问题(解析继续更新)==================
1.析构函数需要作为虚函数吗?
2.构造函数声明的问题:class B(){};
class A:public B{};
main函数:A *a=new B();项目底下请问为何少用B a=new B()来声明?
如果此时用delete a,请问会不会有内存泄漏为什么?
1.2问的是一个事,这里其实是因为,如果父类函数的析构函数没有用虚函数的话,那么在用delete释放对应内存时,子类没有重写虚函数就不会释放子类的内存,因此析构函数是可以作为虚函数,作用就是方便delete时子类释放内存防止内存泄露。
而为何要用A *a=new B();这个声明方式这要看对应的业务场景,网上有一个例子举得很不错,比如父类是People,子类是women或者man,那么如果是一群人群,是不是都可以使用People来初始化呢?这就能解释这样的问题,只是笔者的项目面向对象用的不够精没有碰见这样的场景罢了。
3.delete释放内存的过程是什么样的?请介绍一下。
4.线程和进程的一个内存机制是什么样的?请说明。
进程和线程的机制区别就是,线程用的是连续的内存地址,而不同进程用的是不同的地址空间(这个和分页机制有关系)顺便复习:页表置换算法有哪些? 最佳置换算法、先进先出置换算法、最近最久未使用置换算法、时钟置换算法。
5.什么时候应用占用的内存量会比较大?一下子new太大空间,或者一直new,释放的比new的慢,就容易导致占内存。
6.除了用智能指针避免忘记释放内存外,还有什么其它方法?
除了这样外还可以用内存池的方法来管理内存,在实例销毁时直接销毁内存池。
补充:C++的RALL机制也可以通过析构函数实现内存释放。
7.互斥锁和自旋锁有什么区别?请说明。
自旋锁不会让进程休眠,互斥锁的话会让进程休眠。