迅雷:
1.A *pa = new A[10];
delete pa;
则类A的构造函数和析构函数分别执行了几次()
答案是10,1
分析:如果要删除数组则应该使用delete [] pa,当调用delete pa时,实际上是调用析构函数,析构一个A对象。
2.关于内联函数正确的是()
A、类的私有成员函数不能作为内联函数
B、在所有类说明中内部定义的成员函数都是内联函数
C、类的保护成员函数不能作为内联函数
D、使用内联函数的地方会在运行阶段用内联函数体替换掉
答案是B
分析:因为已知类内部定义的成员函数都是内联函数,所以A、C是错误的,而D:应该是使用内联函数的地方会在编译阶段替换。内联与宏有点类似,但区别在于宏是用预处理器,而内联函数时通过编译器来控制的。
3、下列对函数double add(int a , int b)进行重载,正确的是()
A、int add(int a ,int b ,int c)
B、int add(double a , double b)
C、double add(double a , double b)
D、int add(int a , int b)
答案是ABC。这里正好复习下overload(重载)和override(重写)的区别。
重载:
两个重载函数的名字是相同的,但对于它们的函数参数来说:参数类型,个数,顺序至少有一个不相同,不能重载只有返回值不同的函数,存在父类,子类及同类之间。
重写:
参数类型,个数,顺序都是相同的。
存在于父类和子类之间(即用虚函数实现重写)
注意:子类函数不能缩小父类的访问权限,不能比父类抛出更多异常。
4、请问以下说法,哪个是正确的()
A、每个类都有一个无参数的构造函数
B、每个类都有一个拷贝构造函数
C、每个类能有多个构造函数
D、每个类能有多个析构函数
答案:C
注意:虽然每个类都会生成无参数的构造函数和拷贝构造函数,但只有调用到它们时才会自动生成,所以A,B不完全正确(见effective c++)。
5、某棵完全二叉树上有699个节点,则该二叉树的叶子节点数为()
A、349 B、350 C、188 D、187
答案:350
分析:其实是一道痕基本的题,但刚开始自己的思路有问题。因为完全二叉树的节点规律是:第一次 1个,第二层个数为2.第三层为4,。。。那到第9层总的节点个数为1+2+$+*+16..+256 = 511,所以第十层有(699-511) = 188个节点,但注意这不是最后的答案,因为第九层中没有子节点的也算为叶子节点,个数为(256-188/2)=162,所以总共的数目为(162+188) = 350。
查了一下,网上还有个更方便的公式:(699+1)/2 = 350
6、看以下代码:
#include <iostream>
#include <string>
using namespace std;
class parent{
public:
virtual void output();
};
void parent::output(){
cout<<"parent!"<<endl;
}
class son : public parent{
public:
virtual void output();
};
void son::output(){
cout<<"son"<<endl;
}
int main(){
son s;
memset(&s,0,sizeof(s));
parent &p =s;
p.output();
system("PAUSE");
return 0;
}
输出时:
A、parent! B、son! C、son!parent! D、没有输出结果,程序运行出错
答案D。
解析:关键是memset将s置为空,这样会破坏虚函数指针,导致调用失败。
腾讯:
1、程序的完整编译过程分为是:预处理,编译,汇编等,如下关于编译阶段的编译优化的说法中不正确的是()
A、死代码删除指的是编译过程直接抛弃掉被注释的代码;
B、函数内联可以避免函数调用中压栈和退栈的开销
C、For循环的循环控制变量通常很适合调度到寄存器访问
D、强度削弱是指执行时间较短的指令等价的替代执行时间较长的指令
答案A。
死代码指的是永远不可能执行到的代码,而编译器在某些情况下会判断某些代码根本不影响输出,从而去消除。而D,强度削弱指的是用执行时间短的命令来等价代替一个操作,比如左移代替乘法
2、为了某项目需要,我们准备构造了一种面向对象的脚本语言,例如,对所有的整数,我们都通过Integer类型的对象来描述。在计算“1+2”时,这里的“1”,“2”和结果“3”分别为一个Integer对象。为了降低设计复杂度,我们决定让Integer对象都是只读对象,也即在计算a=a+b后,对象a引用的是一个新的对象,而非改a所指对象的值。考虑到性能问题,我们又引入两种优化方案:(1)对于数值相等的Integer对象,我们不会重复创建。例如,计算“1+1”,这里两个“1”的引用的是同一个对象——这种设计模式叫做()。
答案:享元模式
享元模式(英语:Flyweight Pattern)是一种设计模式。它使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于当大量物件只是重复因而导致无法令人接受的使用大量内存。可以看到,关键是两个1共享同一个对象。
3、在下图的多边形ABCDE中从哪一点出发,可以遍历图上的每条边一次,而且仅遍历一次。
答案是:E或B。
分析:设计到欧拉通路的概念,图中通过中所有边一次且仅一次行遍图中所有顶点的通路称为欧拉通路。在无向图中有欧拉通路的条件为:连通,且仅有两个奇度顶点。在有向图中有欧拉通路的条件为:连通,除去两个顶点(一个入度比出度大一,另一个出度比入度大一),其余的出入度均相等。
4、如下关于链接的说法错误的是()
A、一个静态库中不能包含两个同名全局函数的定义
B、一个动态库中不能包含两个同名全局函数的定义
C、如果两个静态库都包含一个同名全局函数,他们不能同时被链接
D、如果两个动态库都包含一个同名全局函数,他们不能同时被链接
答案 C.
解析:AB编译器保证没有同名函数,C可以的,编译器会保证没有同名,而D不可以,在运行时才调用函数,怎么能保证没同名呢。
5、TCP的关闭过程,说法正确的是()
A)TIME_WAIT状态称为MSL(Maximum Segment Lifetime)等待状态
B)对一个established状态的TCP连接,在调用shutdown函数之前调用close接口,可以让主动调用的一 方进入半关闭状态
C)主动发送FIN消息的连接端,收到对方回应ack之前不能发只能收,在收到对方回复ack之后不能发也不能收,进入CLOSING状态
D)在已经成功建立连接的TCP连接上,如果一端收到RST消息可以让TCP的连洁端绕过半关闭状态并允许丢失数据。
答案 D
分析:网上居然还有答案是C的,误人子弟呀。
首先来看看TCP的关闭过程:
1、客户端向服务器端发送FIN,服务器端收到后回复ACK并关闭服务器读通道,客户端收到ACK之后关闭客户端写通道。
此时服务器端仍然可以写,而客户端仍然可以读服务器端的数据。
2、服务器端发完数据后,向客户端发送FIN,客户端收到FIN后回复ACK给服务器端,同时关闭客户端读通道,服务器端收到ACK后关闭服务器写通道。
注意:服务器端和客户端都可以发出关闭,是对称的。
可以看到C错误。
而在第2步时,客户端回复ACK给服务端同时关闭读写通道时,其实已经断开连接。但此时仍然会处于TIME_WAIT时间,等待一个2倍报文段最大生存时间(MSL),确保所有的连接分组消失,防止确认丢失的情况。所以A是错误的。
对于B:shutdown和close都是关闭连接,但不一样的是shutdown是直接关闭socket描述符,比如多个共享套接字,在其中一个中使用shutdown则其它进程不能访问,而close()是关闭引用计数,如果当前进程是最后一个引用当前socket的则关闭描述符。所以close不一定会让其进入半关闭状态。
D是对的:收到一个不存在的连接返回RST响应,此时调用send,recv都失败,直接绕过了半关闭状态,同时缓冲区的数据可能也丢失掉了。。
6、找工作的季节马上就到了,很多同学去图书馆借阅《面试宝典》这本书,现在图书馆外有6名同学排队,其中3名同学要将手中的《面试宝典》还至图书馆,有3名同学希望从图书馆中可以借到《面试宝典》,若当前图书馆内已无库存《面试宝典》,要保证借书的3名同学可以借到书,请问这6位同学有多少种排队方式。
答案180。
分析:用到卡特兰数。卡特兰数定义如下:h(0) =1,h(1) =1,
h(n) = h(0)*h(n-1)+h(1)*h(n-2)+...+h(n-1)h(0),其解为h(n) = C(2n,n)/(n+1)。
现在我们来分析借书问题。假设有2n个同学,n个同学还书,n个借书。那么联想到了栈的思想,即还书的同学进栈,如果有借书的同学则出栈,则保证能借到书的条件是:栈不为空。
第一个同学肯定是还书的,假设他的书被第k个同学借走,那么必然地,第二个同学到第k-1个同学,第k+1个同学到2n个同学,这两个序列都会满足还书人数=借书人数的条件(为什么?注意栈的性质)。所以k必须为奇数,这样第二个同学到第k-1个同学才能为偶数,否则不满足条件。设k=2i+1,f(n)表示n个同学的序列个数。则第1个同学与第k个配对,序列个数是:
f(2i)*(2n-2i-2)
则推出关系式f(2n) = f(0)*f(2n-2)+f(2)*f(2n-4)....f(2n-2)*f(0)
而f(0) =1,f(2) =1,设f(2n) = h(m),
则h(m) = h(0)*h(m-1)+h(1)*h(m-2)....+h(m-1)*h(0)
符合卡特兰数定义。则h(3) = C(6,3)/4 = 5;
同时注意还书和借书的同学需要全排列,得到最终结果为5*3!*3! = 180。
7、甲、乙两个人在玩猜数字游戏,甲随机写了一个数字,在[1,100]区间之内,将这个数字写在了一张纸上,然后乙来猜。
如果乙猜的数字偏小的话,甲会提示:“数字偏小”
一旦乙猜的数字偏大的话,甲以后就再也不会提示了,只会回答“猜对 或 猜错”
问: 乙至少猜 多少次 猜可以准确猜出这个数字,在这种策略下, 乙猜的第一个数字是 。
答案:14次,14.
分析:注意到每次猜大,都要一个个的去试,所以关键点在于:猜的时候保证每次猜大后,总的猜测次数是一样的。这样会求出最少猜测次数,假设刚开始猜N1,如果猜大了则需要猜N1-1次,总共是N1次,如果猜小了,第二次猜N2大了,则总的猜测为N2-N1+1次。由于两次相等,得到N1 = 2N1-1,增量为N1-1,第三次得到N3 = N2+N1-2,则第K次猜测Nk=N1+(N1-1)+(N1-2)+1,可得N1=14,N2=27.....
8、段页式虚拟存储管理方案的特点
引用网上答案,总结的还挺好。
空间浪费小、存储共享容易、存储保护容易、能动态连接。
段页式管理是段式管理和页式管理结合而成,兼有段式和页式管理的优点,每一段分成若干页,再按页式管理,页间不要求连续(能动态连接);用分段方法分配管理作业,用分页方法分配管理内存(空间浪费小)。
段页式管理采用二维地址空间,如段号(S)、页号(P)和页内单元号(D);系统建两张表格每一作业一张段表,每一段建立一张页表,段表指出该段的页表在内存中的位置;地址变换机构类似页式机制,只是前面增加一项段号。所以存储共享容易、存储保护容易。
完美世界:
1、int a=2,sizeof(a=a+2),则cout<<a<<endl为:
答案 2。
分析:关键sizeof是运算符,优先级和+一样,先算sizeof(a)直接返回了,a仍然为2。
2、设有矩阵A1(30*35)、A2(35*15)、A3(15*5)、A4(5*10),M=A1*A2*A3*A4,下列组合计算M所需数乘次数最少的是:
A、(A1(A2(A3A4))) B、(A1((A2A3)A4)) C、((A1A2)(A3A4)) D、((A1(A2A3))A4) E、(((A1A2)A3)A4)
分析:关键考矩阵的乘法,两个矩阵相乘,前一个的列=后一个的行才可以,比如A1*A2,总的乘数最少为30*35*15。
要求最小,就要最大的先乘,这样在乘的过程中,基数会增长慢,得到最少的次数。
可以看到A2中有最大的35,所以先计算A2*A3 = 35*15*5,之后比较B和D。
D:30*35*5+30*5*10 B:35*5*10+30*35*10 很明显D小。。。其实也符合之前说的准则,即最大的先乘,因为A2乘后就是A1含的30最大了。
3、以下程序输出值是多少?
void func(char (&p)[10])
{
printf("%d\n",sizeof(p));
}
答案:10。
分析:其实p就是引用,所以参数传入函数时不会退化为指针。。。
4、
CONTAINER::iteratoriter , tempIt;
for(iter= cont.begin() ; iter != cont.end() ; )
{
tempIt = iter;
++iter;
cont.erase(tempIt);
}
假设cont是一个CONTAINER的示例,里面包含数个元素,那么当CONTAINER为:
1、vector<int>
2、list<int>
3、map<int , int>
4、deque<int>
答案:1,4
解析:关键是设计到相关容器的性质,一般模板中类似于数组的vector,dequeue,string等做删除操作都会导致迭代器失效,从而崩溃。
5、对于一个空类A,sizeof(A)所占的大小为()。
答案:1
解析:
所谓类的实例化就是在内存中分配一块地址.(空类同样可以被实例化),每个实例在内存中都有一个独一无二的地址,为了达到这个目的,编译器往往会给一个空类隐含的加一个字节,这样空类在实例化后在内存得到了独一无二的地址.因为如果空类不隐含加一个字节的话,则空类无所谓实例化了(因为类的实例化就是在内存中分配一块地址。
6、以下代码
class classA
{
public:
classA()
{
clear();
}
virtual ~classA()
{
}
void clear()
{
memset(this , 0 , sizeof(*this));
}
virtual void func()
{
printf("func\n");
}
};
class classB : public classA
{
};
int main(void)
{
classA oa;
classB ob;
classA * pa0 = &oa;
classA * pa1 = &ob;
classB * pb = &ob;
oa.func(); // 1
ob.func(); // 2
pa0->func(); // 3
pa1->func(); // 4
pb->func(); // 5
return 0;
}
A、func func 执行出错 执行出错 func
B、执行出错 func 执行出错 执行出错 func
C、执行出错 执行出错 执行出错 执行出错 执行出错
D、func func func func func
E、func func 执行出错 func func
F、以上选项都不对
答案:E
分析:关键注意A中的函数clear(),将类置为0破坏了虚指针。而oa.func()和ob.func()不需要访问虚表,只是访问自己的成员函数,所以输出正确。
而pa0->func()运行时会用到多态性质,所以找不到虚表而出错。而B在调用A的构造函数之后会重新构造虚指针,所以pa1->func()是正确的。同理,pb->func()也是正确的。
7、在32位小端的机器上,如下代码输出时什么:
char array[12] = {0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 , 0x08};
short *pshort = (short *)array;
int *pint = (int *)array;
int64 *pint64 = (int64 *)array;
printf("0x%x , 0x%x , 0x%x , 0x%x", *pshort , *(pshort+2) , *pint64 , *(pint+2));
A、0x201 , 0x403 , 0x807060504030201 , 0x0 B、0x201 , 0x605 , 0x807060504030201 , 0x0
C、0x201 , 0x605 , 0x4030201 , 0x8070605 D、0x102 , 0x506 , 0x102030405060708 , 0x0
E、0x102 , 0x304 , 0x1020304 , 0x5060708 F、0x201 , 0x605 , 0x4030201 , 0x6050403
答案:C。
分析:要看此题的考点是什么,肯定不止大小端那么简单(因为大小端都是考滥了的)。
printf要输出64位数需要加入标示符,如:
printf("%I64d/n",a);
printf("%I64u/n",a);
但这里只能输出32位,所以把高32位截去,输出低32位。。同理*(pint+2)也输出低32位。
8、有关引用,下列说法错误的是:
A、引用定义时必须初始化
B、类的非静态引用成员变量不需要在构造函数中初始化
C、数组可以有引用,但没有引用数组
D、public派生对象可以初始化基类类型的引用
E、整型数据的常引用可以直接用数值初始化
F、以上选项都不是
B非静态成员变量是初始化要在构造函数中,而由于引用在创建时就要初始化,所以放到构造函数中其实相当于赋值了(这也是不允许的)。一般来说const和引用都是在初始化列表中进行初始化的。正确。
注意还要初始化列表的另外一种用法是:如果我们有一个类成员,它本身是一个类或者是一个结构,而且这个成员它只有一个带参数的构造函数,而没有默认构造函数,这时要对这个类成员进行初始化,就必须调用这个类成员的带参数的构造函数,如果没有初始化列表,那么他将无法完成第一步。
C数组可以有引用,即数组的别名。例如:int a[3] = {1,2,3};int (&b)[3] = a;数组a和b其实是一样的。而数组中元素不能有引用,例如以下的形式:int &b[3]是不允许的,引用不可以是数组,因为它不支持传统意义上的复制。
D、public派生对象可以用来初始化基类类型的对象的,对于引用来说当然也可以。E、规定是可以的。如const int &a = 1;
所以选F。
9、Windows PE文件装载到的地址为:
A、0x0030000 B、0x0040000 C、任意地址 D、0x10000000
答案:D
分析:PE文件被称为可移植的执行体是Portable Execute的全称,常见的EXE、DLL、OCX、SYS、COM都是PE文件,PE文件是微软Windows操作系统上的程序文件(可能是间接被执行,如DLL)。
10、以下哪些对象可用于Windows进程间通信:
A、事件 B、临界区 C、互斥量 D、共享内存
答案:ACD
分析:注意windows中的临界区(critical_section)只能用于线程之间通信,而事件、互斥量等可以跨进程