笔试选择题二十七
一、存储器(磁盘盒主存)可以用来存储页表
一部分存在磁盘上等待,一部分在主存上。 一旦发生缺页中断,先从主存里面找,有就直接置换,没有再从磁盘把缺失的页面置换到主存中。
因为进程访问具有局部性,所以同一个进程访问的页面都是来来回回都是那几个。磁盘调用发生的频率很低,所以不需要担心访问速度会变慢
二、下面有关回调函数的说法,错误的是?
正确答案: C
回调函数就是一个通过函数指针调用的函数
回调函数可能被系统API调用一次,也可能被循环调用多次
回调函数本身可以是全局函数 ,静态函数和某个特定的类的成员函数
回调函数可用于通知机制
三、假设有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[ ]
在内存的动态分配区域中分配一个长度为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”;
|
p1++;
p1[2] = ‘w’;
p2[2] = ‘l’;
p2++;
只能选A。p1是指向字符常量的指针,p1本身不是常量,所以p1++合法,A正确。 p2本身是指针常量,可以指向非常量的字符。但是"hello"这样声明的字符串是存储在只读存储区的,不可修改,所以B,C,D都错误。
二十、
以下描述错误的是: 正确答案: B你的答案: C (错误)
函数的形参在函数未调用时不分配存贮空间
若函数的定义出现在主函数之前,则可以不必再说明
若一个函数没有return语句,返回类型是void
一般来说,函数的形参和实参的类型应该一致
函数定义在主函数之前...仅仅是说明主函数调用这个函数不会有问题...但是如果函数前还有其他函数调用这个函数就有问题了...
关于C。假如是main函数,无return,它返回的可是int那个编译器会自动给你加上的,不是没有。
推荐阅读
- parallels|parallels desktop 解决网络初始化失败问题
- jhipster|jhipster 升级无效问题
- “精神病患者”的角度问题
- 画解算法(1.|画解算法:1. 两数之和)
- 标签、语法规范、内联框架、超链接、CSS的编写位置、CSS语法、开发工具、块和内联、常用选择器、后代元素选择器、伪类、伪元素。
- 【生信技能树】R语言练习题|【生信技能树】R语言练习题 - 中级
- 解决SpringBoot引用别的模块无法注入的问题
- 如何在Mac中的文件选择框中打开系统隐藏文件夹
- leetcode|leetcode 92. 反转链表 II
- 迷茫是人生常态