如题,这里简要总结一下今年东软校园招聘笔试题中的一些知识点。东软的笔试题一共有两套,第一套称之为通用能力测试,其实就是智力题。第二套称之为专业能力测试,其实就是计算机专业知识的题。这里总结的一些内容主要来自于第二套题,这套题是所谓不分程序语言的,也就是很坑爹地主流三种编程语言(C/C++/Java)的题都会涉及,不过都比较基础,另外还涉及一些基本的关于操作系统、数据结构等计算机科学相关学科的知识。
语言部分:
C:
1、若 x,i,j和k都是int型,则执行表达式 x=(i=4,j=16,k=32)后x的值为多少?(知识点:逗号表达式)
逗号表达式,形如:表达式1,表达式2,表达式3...表达式n,即题中的(i=4, j=16, k=32)。逗号表达式的运算过程是从左至右逐一赋值,当逗号表达式作为一个整体时,它的值为最后一个表达式的值,即k=32。所以本题先计算逗号表达式,然后给x赋值为32。
C++:
1、知识点:虚函数
关于什么是虚函数作简单说明。
简单说,被virtual关键字修饰的成员函数,就是虚函数。虚函数用以实现多态。先看代码:
class A{ public: void print(){ cout<<”This is A”<<endl;} }; class B: public A{ public: void print(){ cout<<”This is B”<<endl;} };不多说,B继承A,重载方法print。现在有main方法的调用:
int main(){ A a; B b; a.print(); b.print(); }>
结果理所当然是:
This is A
This is B
然而,这样无法体现出多态的特性。多态有个关键之处就是一切用指向基类的指针或引用来操作对象。改写main方法如下
int main(){ A a; B b; A* p1=&a; A* p2=&b; p1->print(); p2->print(); }结果却是:
This is A
This is A
指针P2指向的是对象b,调用的却是基类A中的print方法,没有成功实现多态。这时候就应该利用虚函数来实现。改写类A代码
class A{ public: virtual void print(){ cout<<”This is A”<<endl;} };注意,这里print方法加了virtual关键字,表示print方法是个虚函数,加上以后,在因为B类是A类的子类,所以B类中的同名方法默认也是virtual方法了。再运行main方法,结果:
This is AThis is B
总结一下:指向基类的指针在操作它的多态类对象时,会根据不同的类对象,调用其相应的函数,这个函数就是虚函数。
通过虚函数实现多态的机制这里就不深究了,大概知道每个类有一个指针,以及此指针指向的一张表,表里存放着虚函数的地址就可以了。
2、知识点:sizeof
MSDN上的定义:The sizeof keyword gives the amount of storage, in bytes, associated with a variable or a type (including aggregate types). This keyword returns a value of type size_t.
引用之前一篇文章里的话:
看到return这个字眼,是不是想到了函数?错了,sizeof不是一个函数,你见过给一个函数传参数,而不加括号的吗?sizeof可以,所以sizeof不是函数。网上有人说sizeof是一元操作符,但是我并不这么认为,因为C++ sizeof更像一个特殊的宏,它是在编译阶段求值的。
有代码如下:
int a = 0; cout<<sizeof(a=3)<<endl; cout<<a<<endl;
4
3
而实际结果时
4
0
在于C++ sizeof在编译阶段处理的特性。由于sizeof不能被编译成机器码,所以sizeof作用范围内,也就是()里面的内容也不能被编译,而是被替换成类型。=操作符返回左操作数的类型,所以a=3相当于int,而代码也被替换为:
int a = 0; cout<<4<<endl; cout<<a<<endl;
sizeof用法一般两种,sizeof(object)或者sizeof(typename)。前者是对象的size,后者表示数据类型的size。在使用的时候,为了表示语义的明确,一定要加上()。
3、知识点:inline函数的作用,与宏的区别。
首先,关于宏的二义性,举个例,有:
#define MULTI(x) (x*x)调用MULTI(10)当然没有问题,但是当调用MULTI(10+10),就会产生问题了。
接下来说说什么是内联函数,我们可以利用内联函数来解决上面这个宏的问题
inline int MULTI(int x) { return x*x; }这样就不会有歧义了。 看起来和宏差不多,但是比宏多了类型检查,而且内联函数使用的是真正的函数的特性,而不是宏的function-like,模拟函数的功用。
所以,内联函数就是小型函数,牺牲空间来节省函数调用的开销,一般用作比较小的函数,即函数内部没有循环、开关语句等。内联函数被发明出来就是为了取代C中的宏,因为宏是单纯的替换而没有类型检查所以经常出毛病
下面一段话更好地阐释了内联函数的作用:
函数是一种更高级的抽象。它的引入使得编程者只关心函数的功能和使用方法,而不必关心函数功能的具体实现;函数的引入可以减少程序的目标代码,实现程序代码和数据的共享。但是,函数调用也会带来降低效率的问题,因为调用函数实际上将程序执行顺序转移到函数所存放在内存中某个地址,将函数的程序内容执行完后,再返回到转去执行该函数前的地方。这种转移操作要求在转去前要保护现场并记忆执行的地址,转回后先要恢复现场,并按原来保存地址继续执行。因此,函数调用要有一定的时间和空间方面的开销,于是将影响其效率。特别是对于一些函数体代码不是很大,但又频繁地被调用的函数来讲,解决其效率问题更为重要。引入内联函数实际上就是为了解决这一问题。
在程序编译时,编译器将程序中出现的内联函数的调用表达式用内联函数的函数体来进行替换。显然,这种做法不会产生转去转回的问题,但是由于在编译时将函数休中的代码被替代到程序中,因此会增加目标程序代码量,进而增加空间开销,而在时间代销上不象函数调用时那么大,可见它是以目标代码的增加为代价来换取时间的节省。
它与宏的区别在于:
(1)宏是由预处理器对宏进行替代,而内联函数是通过编译器控制来实现的。
(2)内联函数是真正的函数,只是在需要用到的时候,内联函数像宏一样的展开,所以取消了函数的参数压栈,减少了调用的开销。你可以象调用函数一样来调用内联函数,而不必担心会产生于处理宏的一些问题。
此外,它们的代码效率是一样,但是内联欢函数要优于宏定义,因为内联函数遵循的类型和作用域规则,它与一般函数更相近,在一些编译器中,一旦关上内联扩展,将与一般函数一样进行调用,比较方便。
P.S. 函数体在类体内的函数默认为内联函数。
4、知识点:默认构造函数,默认拷贝构造函数
默认构造函数是由编译器在用户没有定义任何形式的构造函数的情况下自动添加的,它只能完成空间的分配,它不能完成对类的数据成员的初始化工作,若用户在用其它方式初始化这些数据成员之前对它们进行访问,就会出错.因此,在任何情况下,用户都应该自定义构造函数,而不使用编译器提供的默认构造函数。
而若用户没有定义拷贝构造函数,则编译器自动添加默认拷贝构造函数(带一个该类类型的参数),称为浅拷贝.它只能完成基本类型数据类型(如int型变量)的拷贝,若类中有动态数组等数据类型,浅拷贝就会出问题.即是说,浅拷贝有潜在危险(当类的数据成员都是基本类型数据类型时,它是安全的).因此,在任何情况下,用户自定义拷贝构造函数是可取的.