笔试选择题二十七

一、存储器(磁盘盒主存)可以用来存储页表
一部分存在磁盘上等待,一部分在主存上。 一旦发生缺页中断,先从主存里面找,有就直接置换,没有再从磁盘把缺失的页面置换到主存中。
因为进程访问具有局部性,所以同一个进程访问的页面都是来来回回都是那几个。磁盘调用发生的频率很低,所以不需要担心访问速度会变慢

二、下面有关回调函数的说法,错误的是?
正确答案: C

回调函数就是一个通过函数指针调用的函数

回调函数可能被系统API调用一次,也可能被循环调用多次

回调函数本身可以是全局函数 ,静态函数和某个特定的类的成员函数

回调函数可用于通知机制

核心就是类成员函数需要this指针访问函数,而全局或者静态函数不需要this指针。 简言之, 类的成员函数需要隐含的this指针 而回调函数没有办法提供。 基础概念: 回调函数就是一个通过函数指针调用的函数。 如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。 回调函数不是由该函数的实现方法直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
三、假设有4条语句s1:a=5x; s2:b=5+y; s3:c=a+b; s4:d=c+y; 根据bernstein条件,下面说法正确的是?
正确答案: A你的答案: A (正确)
s3,s4不可并发执行

s2,s3可并发执行

s1,s4可并发执行

s1,s2不可并发执行

【笔试选择题二十七】
Bernstein条件就是讲两个过程如果有数据冲突(Data hazard),那么就没法并行执行。比如过程A生成数据d,而过程B需要输入数据d,那么B就需要A的输入,他们就没法并行执行(写后读问题,RAW)。如果二者会影响后续过程需要的数据,尤其是该数据和他们执行的顺序很有关系,那么他们同样也不能并行执行(写后写问题, WAW)。

s1和s4互相影响了,s4中的c=a+b与s1中的a冲突

四、在段页式存储管理系统中其虚拟地址空间是(三维)的。要注意段页式有三个量,段号、页号、页内偏移量
五、有作业控制块JCB连成一串而形成的排队队列称为()。
正确答案: D
挂起队列

阻塞队列

就绪队列

后备队列


高级调度 (作业调度或长程调度JCB ):后备队列
中级调度 (中程调度 pcb):就绪队列,阻塞队列,
低级调度 (进程调度或短程调度pcb):挂起队列 or 就绪队列 or 阻塞队列

六、下面关于迭代器失效的描述哪个是错误的()
正确答案: A
vector的插入操作不会导致迭代器失效

map的插入操作不会导致迭代器失效

vector的删除操作只会导致指向被删除元素及后面的迭代器失效

map的删除操作只会导致指向被删除元素的迭代器失效



vector是顺序存储的, vector容器插入操作,全部迭代器失效,不管是前面的还是后面的; map是映射,key和value是一一对应的,在内存中是零散存在的,迭代器通过key找到value,无论怎么插入都不会让迭代器失效,当然删除只会使得被删除元素的迭代器失效
七、下面对静态数据成员的描述中,正确的是?
正确答案: D
静态数据成员可以在类体内进行初始化

静态数据成员不可以被类的对象调用

静态数据成员不受private控制符的作用

静态数据成员可以直接用类名调用



static 数据成员只能类外初始化C++ 11 标准之前 只允许 static const 成员变量声明时初始化 const 成员变量与引用只能在构造函数初始化表中初始化 int 之类的既可以在初始化表也可以在构造函数中初始化 C++ 11 标准后 允许非静态成员数据在声明时初始化 const int 之类的都可以在声明时就初始化
八、
单道程序系统几个特点: 1. 资源独占性
任何时候,位于内存中的程序可以使用系统中的一切资源,不可能有其他程序与之竞争
2. 执行的顺序性 内存中只有一个程序,各个程序是按次序执行的。在做完一个程序的过程中,不可能夹杂进另一个程序执行
3. 结果的可再现性 只要执行环境和初始条件相同,重复执行一个程序,获得的结果总是一样的
4. 运行结果的无关性 程序的运行结果与程序执行的速度无关。系统中的作业以串行的方式被处理,无法提高CPU、内存的利用率 本来就是有序的,故 不需要同步互斥 九、并发进程执行的相对速度是(与进程调度策略有关)。
一个进程运行时由于自身或外界的原因而可能被中断,且断点是不固定的。一个进程被中断后,哪个进程可以运行呢?被中断的进程什么时候能再去占用处理器呢?这是与进程调度策略有关的。所以,进程执行的相对速度不能由进程自己来控制,于是,就可能使并发进程在共享资源时出现与时间有关的错误。
十、连通分量指的是无向图中的极大连通子图

在无向图中,如果从顶点vi到顶点vj有路径,则称vi和vj连通。如果图中任意两个顶点之间都连通,则称该图为连通图,否则,称该图为非连通图,则其中的极大连通子图称为连通分量,这里所谓的极大是指子图中包含的顶点个数极大。 十一、 C++11 STL 中的容器 ================================================== 一、顺序容器:
vector:可变大小数组; deque:双端队列; list:双向链表; forward_list:单向链表; array:固定大小数组; string:与vector相似的容器,但专门用于保存字符。 ================================================== 二、关联容器: 按 关键字有序保存元素:(底层实现为 红黑树) map:关联数组;保存关键字-值对; set:关键字即值,即只保存关键字的容器; multimap:关键字可重复的map; multiset:关键字可重复的set; -------------------------------------------------------------------------------- 无序集合: unordered_map:用哈希函数组织的map; unordered_set:用哈希函数组织的set; unordered_multimap:哈希组织的map;关键字可以重复出现; unordered_multiset:哈希组织的set;关键字可以重复出现。 ================================================== 三、其他项: stack、queue、valarray、bitset 十二、下面哪种C/C++ 分配内存的方法会将分配的空间初始化为0

正确答案: B
malloc()

calloc()

realloc()

new[ ]

1) malloc 函数: void *malloc(unsigned int size)
在内存的动态分配区域中分配一个长度为size的连续空间,如果分配成功,则返回所分配内存空间的首地址,否则返回NULL,申请的内存不会进行初始化。
2)calloc 函数: void *calloc(unsigned int num, unsigned int size) 按照所给的数据个数和数据类型所占字节数,分配一个 num * size 连续的空间。
calloc申请内存空间后,会自动初始化内存空间为 0,但是malloc不会进行初始化,其内存空间存储的是一些随机数据。
3)realloc 函数: void *realloc(void *ptr, unsigned int size) 动态分配一个长度为size的内存空间,并把内存空间的首地址赋值给ptr,把ptr内存空间调整为size。
申请的内存空间不会进行初始化。
4)new是动态分配内存的运算符,自动计算需要分配的空间,在分配类类型的内存空间时,同时调用类的构造函数,对内存空间进行初始化,即完成类的初始化工作。动态分配内置类型是否自动初始化取决于变量定义的位置,在函数体外定义的变量都初始化为0,在函数体内定义的内置类型变量都不进行初始化。 十三、若有
1 char st1[12]= "Yes" , st2[5]= "No" , st3[7]= "Or" ;
, 则执行下列语句,输出结果是_________。
1 cout<< strcat ( strcat (st1,st3), st2);
YesOrNo


st1,st2,st3 存储的都是C 风格的字符串,都以null 字符结束。 strcat 函数将后面的字符串连接到前面的字符串,且会覆盖null 字符,所以就是选A。

十四、关于c++的inline关键字,以下说法正确的是()
正确答案: D
使用inline关键字的函数会被编译器在调用处展开

头文件中可以包含inline函数的声明

可以在同一个项目的不同源文件内定义函数名相同但实现不同的inline函数

定义在Class声明内的成员函数默认是inline函数

优先使用Class声明内定义的inline函数

优先使用Class实现的内inline函数的实现



内联函数:
Tip: 只有当函数只有 10 行甚至更少时才将其定义为内联函数.
定义: 当函数被声明为内联函数之后, 编译器会将其内联展开, 而不是按通常的函数调用机制进行调用.
优点: 当函数体比较小的时候, 内联该函数可以令目标代码更加高效. 对于存取函数以及其它函数体比较短, 性能关键的函数, 鼓励使用内联.
缺点: 滥用内联将导致程序变慢. 内联可能使目标代码量或增或减, 这取决于内联函数的大小. 内联非常短小的存取函数通常会减少代码大小, 但内联一个相当大的函数将戏剧性的增加代码大小. 现代处理器由于更好的利用了指令缓存, 小巧的代码往往执行更快。
结论: 一个较为合理的经验准则是, 不要内联超过 10 行的函数. 谨慎对待析构函数, 析构函数往往比其表面看起来要更长, 因为有隐含的成员和基类析构函数被调用!
另一个实用的经验准则: 内联那些包含循环或 switch 语句的函数常常是得不偿失 (除非在大多数情况下, 这些循环或 switch 语句从不被执行).
有些函数即使声明为内联的也不一定会被编译器内联, 这点很重要; 比如虚函数和递归函数就不会被正常内联. 通常, 递归函数不应该声明成内联函数.(递归调用堆栈的展开并不像循环那么简单, 比如递归层数在编译时可能是未知的, 大多数编译器都不支持内联递归函数). 虚函数内联的主要原因则是想把它的函数体放在类定义内, 为了图个方便, 抑或是当作文档描述其行为, 比如精短的存取函数.
-inl.h文件:

Tip: 复杂的内联函数的定义, 应放在后缀名为 -inl.h 的头文件中.

内联函数的定义必须放在头文件中, 编译器才能在调用点内联展开定义. 然而, 实现代码理论上应该放在 .cc 文件中, 我们不希望 .h 文件中有太多实现代码, 除非在可读性和性能上有明显优势.
如果内联函数的定义比较短小, 逻辑比较简单, 实现代码放在 .h 文件里没有任何问题. 比如, 存取函数的实现理所当然都应该放在类定义内. 出于编写者和调用者的方便, 较复杂的内联函数也可以放到 .h 文件中, 如果你觉得这样会使头文件显得笨重, 也可以把它萃取到单独的 -inl.h 中. 这样把实现和类定义分离开来, 当需要时包含对应的 -inl.h 即可。

A 如果只声明含有inline关键字,就没有内联的效果。 内联函数的定义必须放在头文件中, 编译器才能在调用点内联展开定义.有些函数即使声明为内联的也不一定会被编译器内联, 这点很重要; 比如虚函数和递归函数就不会被正常内联. 通常, 递归函数不应该声明成内联函数. B 内联函数应该在头文件中定义,这一点不同于其他函数。编译器在调用点内联展开函数的代码时,必须能够找到 inline 函数的定义才能将调用函数替换为函数代码,而对于在头文件中仅有函数声明是不够的。 C 当然 内联函数定义也可以放在源文件中,但此时只有定义的那个源文件可以用它,而且必须为每个源文件拷贝一份定义(即每个源文件里的定义必须是完全相同的),当然即使是放在头文件中,也是对每个定义做一份拷贝,只不过是编译器替你完成这种拷贝罢了。但相比于放在源文件中,放在头文件中既能够确保调用函数是定义是相同的,又能够保证在调用点能够找到函数定义从而完成内联(替换)。 对于由两个文件compute.C和draw.C构成的程序来说,程序员不能定义这样的min()函数,它在compute.C中指一件事情,而在draw.C中指另外一件事情。如果两个定义不相同,程序将会有未定义的行为: 为保证不会发生这样的事情,建议把inline函数的定义放到头文件中。在每个调用该inline函数的文件中包含该头文件。这种方法保证对每个inline函数只有一个定义,且程序员无需复制代码,并且不可能在程序的生命期中引起无意的不匹配的事情。
D 正确。 定义在类声明之中的成员函数将自动地成为内联函数,例如:
1 class A { public : void Foo( int x, int y) { ... } // 自动地成为内联函数}

EF 在每个调用该inline函数的文件中包含该头文件。这种方法保证对每个inline函数只有一个定义,且程序员无需复制代码,并且不可能在程序的生命期中引起无意的不匹配的事情。 最好只有一个定义!
十五、以下程序的输出是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class Base { public : Base( int j): i(j){} virtual ~Base() {} void func1() { i *= 10; func2(); } int getValue() { return i; } protected : virtual void func2() { i++; } protected : int i; }; class Child: public Base { public : Child( int j): Base(j) {} void func1() { i *= 100; func2(); } protected : void func2() { i += 2; } }; int main() { Base * pb = new Child(1); pb->func1(); cout << pb->getValue() << endl; delete pb; } 输12 Base * pb = new Child(1), 首先创建子类对象,初始化为1; func1()不是虚函数,所以pb->func1()执行的是基类的func1函数,i= 10,然后调用func2()函数; 这里的func2是虚函数,要往下派生类寻找,找到后执行派生类中的func2(),此时,i = 12; 最后执行pb->getValue(),结果为12

十六、麦秋时节,庄园主雇了个力大无穷的农民来帮他收割田里的麦子。收获的劳动量很大,农民必须在七天之内收割完。庄园主答应每天给他一块金块作工钱。但是这七块相等的金子是连在一起的,然而工钱是必须每天结清的。农民不愿意庄园主欠帐,而庄园主也不肯预付一天工钱。请问最少掰金子几次可以完成上述任务?

1、第一天,庄园主掰1块金给农民,付第一天的。农民:1;庄园主:6 2、第二天,庄园主从剩下的6块里面掰下2块给农民,并收回第一天的一块。农民:2;庄园主:1+4 3、第三天,庄园主将手里的一块散金给农民。农民:2+1;庄园主:4 4、第四天,庄园主收回农民手里的三块金,并把手里的金给农民。农民:4;庄园主:2+1 5、第五天,庄园主把手里的1块散金给农民。农民:4+1;庄园主:2 6、第六天,庄园主收回农民手里的1块散金,将2块金给农民。农民:4+2,庄园主:1 7、第七天,庄园主将手里的金块给农民。农民:7,庄园主:0 综上,一共掰了两次。
十七、在N个乱序数字中查找第k大的数字,时间复杂度可以减小至
正确答案: B
O(N*logN)

O(N)

O(1)

O(2)



http://www.cnblogs.com/fengkang1008/p/4727038.html

十八、以下选项中非法的C语言字符常量是?
正确答案: D
'\007'

'\b'

'a'

'\09'



转义字符 意义 ASCII码值(十进制) \0 空字符(NULL) 000 \ddd 任意字符 三位八进制 \xhh 任意字符 二位十六进制

转移字符分三种,一般转义字符,八进制转移字符和十六进制转移字符 一般转义字符,如‘\b’,由两个字符表示,其实代表一个字符,这个代表退格字符 八进制转义字符,如‘\007’,三位数字是八进制的,ASCII码为7的表示响铃 十六进制,如'\xfe',同样后面数字是所表示意思的Ascii码的十六进制表示,注意一定要有x,大小写都行
十九、给出以下定义,下列哪些操作是合法的?
1 2 const char *p1 = “hello”; char * const p2 = “world”;
正确答案: A你的答案: A (正确)
p1++;

p1[2] = ‘w’;

p2[2] = ‘l’;

p2++;



只能选A。p1是指向字符常量的指针,p1本身不是常量,所以p1++合法,A正确。 p2本身是指针常量,可以指向非常量的字符。但是"hello"这样声明的字符串是存储在只读存储区的,不可修改,所以B,C,D都错误。
二十、
以下描述错误的是: 正确答案: B你的答案: C (错误)
函数的形参在函数未调用时不分配存贮空间

若函数的定义出现在主函数之前,则可以不必再说明

若一个函数没有return语句,返回类型是void

一般来说,函数的形参和实参的类型应该一致


B
函数定义在主函数之前...仅仅是说明主函数调用这个函数不会有问题...但是如果函数前还有其他函数调用这个函数就有问题了...
关于C。假如是main函数,无return,它返回的可是int那个编译器会自动给你加上的,不是没有。

    推荐阅读