4大学期末考试计算机面试和笔试题知识.docx
- 文档编号:8111580
- 上传时间:2023-01-28
- 格式:DOCX
- 页数:46
- 大小:5.06MB
4大学期末考试计算机面试和笔试题知识.docx
《4大学期末考试计算机面试和笔试题知识.docx》由会员分享,可在线阅读,更多相关《4大学期末考试计算机面试和笔试题知识.docx(46页珍藏版)》请在冰豆网上搜索。
4大学期末考试计算机面试和笔试题知识
一、基础知识wss
1.各类修饰符的作用:
static的作用:
(1)函数体内(数据长久性)
作用范围就是该函数体,并只分配一次内存,且在下一次调用时,其值会维持为上一次调用时的值;(auto变量则是每次调用时清零)
(2)文件/模块中(数据隐藏性):
a.普通全局变量/函数:
具有全局可见性(即在所有文件中都可见:
若本文件中没有该全局变量,则通过extern进行扩展);
b.静态全局变量/函数:
具有局部可见性(即只在当前文件/模块内可见);
(3)默认初始化值为0,原因是静态数据区默认值为0,因此可以减少程序员的工作量。
(4)类中的静态数据成员:
1.被该类所有对象所共享(包括其派生类);
2.独立于类对象而存在,不是类对象的组成部分(因此sizeof时不计算在内);
3.只能在类外定义或者初始化(静态成员变量被该类所有对象所共享,因此如果在该类内部进行定义,容易引起混乱)。
(5)类中的静态成员函数:
1.被该类所有对象所共享(包括其派生类);
2.没有this指针,因此只能调用静态数据成员,而无法调用普通数据成员;
3.不可被声明为virtual、const;
4.无需创建类对象可实现函数访问,即可通过类作用域直接访问;
const的作用:
(1)用于普通变量:
将被修饰变量定义为常量,以防止被修改;
(2)用于函数返回值类型:
string类型的加法赋值函数返回s=s1+s2;
(3)用于函数形参类型:
防止形成被修改,并且扩展形参范围(const形参可以接受const或非const实参,而非const形参只能接受非const实参);
(3)用于修饰函数体:
const成员函数无法修改其调用类对象的数据成员(若用mutable修饰后,则可修改其数据成员);
(4)关于volatile:
类似于const,但是在编译器认识范围之外可以被改变。
&引用的作用:
(作用类似于指针)
(1)用于普通变量:
其是目标变量的一个别名,对其进行操作相当于对目标变量进行操作;其不占用内存空间;(数组没有引用)
(2)用于函数返回类型;(用于连续赋值)
(3)用于函数形参:
引用传递和地址传递的效果是相同的,即函数中所有对形参的操作都是对主函数中实参的操作(但是指针形参会产生形参副本和存储单元);此外,引用形参不产生形参副本且不产生存储单元,即直接使用实参本身,并使用用于大型数据的形参传递,可提高运行效率(对于普通形参,会产生形参副本并分配存储单元,对于类对象形参还会调用拷贝构造函数);
(4)const&(常引用):
经常用作函数形参类型,const作用是使得形参无法被修改,&作用是避免调用复制构造函数,提高代码效率;
(5)可用于产生多态(Derivedd;Base&b=d;)
(6)引用与指针的区别
1.引用必须被初始化,指针不必初始化;
2.不能改变引用所指对象,可以改变指针所指对象;
3.不存在指向空值的引用,但是存在指向空值的指针。
2.#define(宏定义)的相关讨论
宏定义(注意括号的使用以防止边界效应,没有分号):
#definemin(a,b)(((a)<(b))?
(a):
(b))
a.#define与const
相同点:
二者均可定义常量;
不同点:
(1)编译器处理方式不同
define是在预处理阶段展开。
const是编译运行阶段使用。
(2)类型和安全检查不同
define宏没有具体类型,没有类型检查。
(存在边际效应)
const常量有具体类型,有类型检查。
(3)存储方式不同
define宏仅仅是展开,有多少地方使用,就展开多少次,不会分配内存。
const常量仅有一份拷贝,且会在内存中分配。
(4)调试工具
define没有集成化调试工具可以对其进行调试。
const有集成化调试工具可以对其进行调试。
b.#define与inline(内联函数)
相同点:
二者均可定义函数;
不同点:
宏定义函数只是函数的简单替换和展开,因此安全性较差。
inline函数不是函数跳转,而是直接将代码写入该行,提升了效率,安全性更高。
3.new与malloc的区别
(1)malloc和free是C++\C语言的标准库函数,new和delete是C++运算符,都用于动态内存分配和删除;
(2)malloc不能初始化类对象,new可以初始化类对象,new会调用对象的构造函数进行对象初始化。
Delete会调用对象的destructor,而free不会调用对象的destructor;
(3)new带有具体指针类型,而malloc不带有指针类型并始终返回void*。
4.堆stack和栈heap的区别
(1)管理方式:
a.栈中内存空间由系统编译器自动申请和释放;
b.堆中内存空间则由用户手动申请和释放(new、malloc);
(2)分配方式:
a.栈可进行静态和动态内存分配:
inti=1;int*ptr=newint[10];
b.堆只可进行动态内存分配;
newint[10];(int*)malloc(sizeof(int)*n);
(3)空间大小:
a.栈有空间大小限制;
b.堆没有空间大小限制;
(4)申请效率:
栈>堆;
(5)碎片问题:
a.栈:
是一种向低地址扩展的数据结构,连续内存空间,不易产生碎片,;
b.堆:
是一种向高地址扩展的数据结构,非连续内存空间(通过遍历链表,该链表记录了空闲内存地址),易产生碎片。
5.struct和class的区别
struct和class一样,可以含有数据成员和成员函数、继承、多态。
(1)默认访问权限:
struct默认是public,class默认是private。
(2)默认继承权限:
struct默认是public,class默认是private。
(3)实现
struct更适合实现数据结构,class更适合实现类对象。
6.sizeof()操作符的使用问题:
(1)void(charstr[100])
{
ints=sizeof(str);//无论str[]中的维数是多大,此时s=4
returns;
}
原因:
实参数组传入到函数的形参中,此时形参数组会退化成指针,相当于传递了一个指针变量(即长整型地址变量long),因此sizeof(str)==sizeof(long)=4。
(2)classA
{
//空类
}a;
sizeof(a)=1;
原因:
空类不含有数据成员或成员函数,理论上不占用内存空间。
但是,空类是可以进行实例化的,而一旦进行实例化后该对象则会占用内存空间。
因此,系统为保证空类在实例化过程中不会出错会分配给空类一定的内存空间,32位系统下所分配的内存空间1byte。
6.函数重载、覆盖、隐藏
重载是指相同的函数名,但参数的类型或个数中只要有所不同,便进行再定义,编译之后重载的函数都具有不同的地址,也就是说虽然函数名相同,实际上是不同的函数,在调用时,编译系统会根据不同之处自动区别是调用哪一个函数。
对于普通函数和后面要学的类的成员函数都适用。
它们的地址在编译时就确定了,和多态无关。
覆盖(也叫重写)只对类的构造函数或成员函数适用,是子类继承父类是才使用的非常有用的功能。
真正和多态相关。
它们的地址在编译时无法确定,在运行时动态分配。
重载可以针对运算符,而覆盖不行。
隐藏:
是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
(1)如果派生类的函数与基类的函数同名,但是参数不同。
此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。
此时,基类的函数被隐藏(注意别与覆盖混淆)
区别:
重载(overload):
(1)作用范围:
同一个类内;
(2)函数名相同;
(3)函数参数不同(返回值类型、参数个数或参数类型)。
覆盖(override):
(1)作用范围:
分别在基类和派生类;
(2)函数名相同;
(3)函数参数相同(返回值类型、参数个数与参数类型);
(4)有virtual标识。
隐藏(hide):
(1)作用范围:
分别在基类和派生类;
(2)函数名相同:
(3)a.若函数参数不同(个数和类型),则无论有无virtual标识,构成隐藏;
b.若函数参数相同(个数和类型),且无virtual标识,构成隐藏;
7.内存分配方式
1.动态数据区
(1)栈区(stack)— 程序运行时由编译器自动分配,存放函数的参数值,局部变量的值等。
其操作方式类似于数据结构中的栈。
程序结束时由编译器自动释放。
(2)堆区(heap) —在内存开辟另一块存储区域。
一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。
注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
用malloc,calloc,realloc等分配内存的函数分配得到的就是在堆上
2.静态数据区:
全局区(静态区)(static)—编译器编译时即分配内存。
全局变量和静态变量的存储是放在一块的。
对于C语言初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。
而C++则没有这个区别-程序结束后由系统释放
3.文字常量区 —常量字符串就是放在这里的。
程序结束后由系统释放
4.程序代码区—存放函数体的二进制代码。
(1)全局变量和局部变量在内存中有什么区别?
编译器如何区分二者?
1.存储区域不同:
全局变量储存在静态数据区,局部变量存在动态数据区。
(内存分配:
动态存储区域(堆、栈:
局部变量)、代码区、常量区、静态存储区域(全局、静态变量static))。
2.作用范围不同:
全局变量的生命周期从程序开始到程序结束,而局部变量的生命周期仅仅是在函数体内。
编译器根据变量声明位置进行判断。
(2)字符串数组的全局和局部变量形式:
局部数组:
(str被存于栈内,即动态数据区)
全局变量:
(str被存于栈内,但由于后面的字符串常量复制,最后返回相当于返回一个全局变量,因此保存在内存中的静态数据区)
静态变量:
(保存在内存中的静态数据区)
8.线性表(前后元素是1对1关系)的顺序与链式存储结构的比较
1.顺序存储结构:
优点:
1)随机存取(时间复杂度为O
(1):
查找第i个元素只需找到(i-1)位置);
2)无需为表示表中元素之间的逻辑关系而增加额外的存储空间;
缺点:
1)插入、删除操作需要移动大量元素,效率低(时间复杂度为O(n));
2)表的长度难以确定
2.链式存储结构
优点:
1)插入、删除不需要移动数据,效率高(时间复杂度为O
(1));
缺点:
1)存取时需要遍历,效率低(时间复杂度为O(n));
3、适用的场合
顺序存储结构:
频繁查找,较少插入、删除;
链式存储结构:
较少查找,频繁插入、删除;
9.各种排序算法比较
10.STL容器:
STL容器:
vector封装数组,list封装了链表,map和set封装了二叉树等;
封装的常用操作:
统计(count)、查找(find)、排序(sort)、插入(insret)、删除(erase)等。
map容器(键-值的映射)
(1)底层实现:
红黑树,查找时间复杂度是O[log(n)];
(2)支持下标操作;
(3)每个键都唯一,排序,键不能被修改,值可以被修改;
(4)multimap允许键重复;
(5)hash_map采用哈希表存储,查找时间复杂度是O
(1)。
set容器(键的集合)
(1)底层实现:
红黑树,查找时间复杂度是O[log(n)];
(2)不支持下标操作;
(3)每个键都唯一,排序,键不能被修改;
(4)包含并集、交集、差集运算;
(5)Multiset允许键重复;
(6)hash_set采用哈希表存储,查找时间复杂度是O
(1)。
map和hash_map的区别:
(1)时间复杂度:
map是O[log(n)],而hash_map则是O
(1);
(2)比较函数:
map是小于函数,而hash_map是等于函数;
(3)存储结构:
map是红黑树,而hash_map是哈希表;
(4)综合考虑:
a.需考虑耗时少:
采用hash_map(map的时间复杂度较高);
b.需考虑内存占用少:
采用map(hashmap的哈希表的内存消耗比较大)。
根据value值对map进行排序
a.将map容器中的内容导入到vector容器中;(直接初始化或循环导入)
b.定义谓词比较函数,并利用sort函数进行排序;
11.泛型编程与模板
C++中为什么用模板类?
1)可用来创建动态增长和减小的数据结构;
2)它是与类型无关的,因此具有很高的代码重用性,是泛型编程的基础;
3)它在编译时而不是运行时检查数据类型,保证了类型安全;
4)可跨平台,可移植性;
5)可用于基本数据类型。
泛型编程是独立于任何特定类型的方式编写代码,并以模板为基础。
泛型编程所编写出的类和函数能够跨越编译时的不同类型,因此能够操纵不同类型的对象。
并独立于类型。
模板包括:
模板类和模板函数。
(1)函数模板
实例化:
abs(1.2);abs
(1);
Max(1.3,1.5);Max(5,6);
(2)类模板
实例化:
MyTermClass
12.运算符优先级:
13.平衡二叉树?
树内的所有节点的左右子树都是平衡二叉树 即左右子树的深度差值的绝对值不大于1。
14.结构化程序的三种基本结构
顺序结构、分支结构、循环结构
15.BOOL,int,float,指针类型的变量a与零的比较语句。
答:
BOOL:
if(!
a)
int:
if(a==0)
float:
constEXPRESSIONEXP=0.000001(浮点数0存储时可能存在误差)
if(a
pointer:
if(a!
=NULL)
16.原码、反码、补码的关系:
(符号位:
0-正,1-负)
正数:
原码=反码=补码
负数:
反码=原码各位取反(符号位不变)
补码=原码各位取反后+1(符号位不变)
注:
(1)负数原码+负数补码==0;
(2)计算机系统内,系统用补码存储:
17.不能做switch()的参数类型是:
switch的参数不能为实型:
单精度(float),双精度(double)和长双精度(longdouble)型。
18.头文件中的 ifndef/define/endif 干什么用?
有两个C文件,这两个C文件都include了同一个头文件。
而编译时,这两个C文件要一同编译成一个可运行文件,于是问题来了,大量的声明冲突。
使用这个就可避免重复引用。
19.strcpy、memcpy及sprintf之间的区别
char*strcpy(char*dst,char*src);//只对字符串进行复制,以’\0’为结束符;
char*strncpy(char*dst,char*src,size_tn);//对源字符串中的前n个字符进行拷贝;
void*memcpy(void*dst,constvoid*src,size_tn);//对任意类型的n个字节内存中的内容进行复制(内存不可重叠)
void*memmove(void*dst,constvoid*src,size_tn);//对任意类型的n个字节内存中的内容进行复制(内存可重叠)
void*memset(void*dst,intsrc, size_t n);//对任意类型进行n个src数据的初始化;
intsprintf(char*buffer,[待转换变量类型],[待转换变量]);//任意类型数据到字符串的格式转换
20.自增运算符(i++,++i):
21.a++与++a的区别
后缀式a++:
返回的是a的副本,即一个临时变量,因此不能作为左值
前缀式++a:
返回的是a的本身,因此可以作为左值
22.运算优先级:
23.伙伴地址:
假设p为大小为2^k的空闲块的初始地址。
1.Pmod2^(k+1)==0,则初始地址为p和p+2^k的两个空闲块互为伙伴;
2.Pmod2^(k+1)!
=0,则初始地址为p和p-2^k的两个空闲块互为伙伴。
24.内置类型的内存大小:
注:
sizeof(指针*)=4(32位系统)
25.#include
#include
#include“filename.h”,编译器从用户工作路径开始搜索filename.h。
26.在C++程序中调用被C编译器编译后的函数,为什么要加extern“C”?
C++语言支持函数重载,C语言不支持函数重载。
函数被C++编译后在库中的名字与C语言的不同。
假设某个函数的原型为:
voidfoo(intx,inty);该函数被C编译器编译后在库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。
C++提供了C连接交换指定符号extern“C”来解决名字匹配问题。
27.ASCII码
数字0-9(48-57)大小写字母(A-65、a-97)。
28.size_type和size_t的区别。
size_type:
由string类类型和vector类类型定义的类型,用以保存任意string对象或vector对象的长度,标准库类型将size_type定义为unsigned类型。
size_t:
数组下标的正确类型则是size_t。
它是一个与机器相关的unsigned类型,其大小足以保证存储内存中对象的大小。
29.接口定义规范
SOA:
面向服务的体系结构service-orientedarchitecture
基本特征如下:
可从企业外部访问
随时可用
粗粒度的服务接口分级
松散耦合
可重用的服务
服务接口设计管理
标准化的服务接口
支持各种消息模式
精确定义的服务契约
30.MFC中的常用类
CDocument:
用户文档基类,用于读取和保存文件,并将数据从用户界面中独立出来。
CView:
用户视图基类,用于显示数据。
31.数据库视图(createview)
(1)简单性:
建立视图实现对整个数据库中部分感兴趣的数据进行操作,并且屏蔽了数据库构建过程的复杂过程,从而简化用户对于数据的操作;
(2)安全性:
通过视图只能看见部分可操作的数据,而无法看到数据库中其余数据;
(3)独立性:
将应用程序与数据相互分离和独立;
(4)多角度性。
32.数据库索引(createindex)
作用:
加快记录的查找速度;
原理:
B树,B+树等二叉查找树;
类型:
唯一索引、主键索引和聚集索引。
33.“内存泄露(溢出)”和“指针引发的程序崩溃”
(1)内存泄露:
a.动态开辟的内存没有被及时释放,导致溢出;
b.析构函数:
多态中,未将基类析构函数设置为虚函数,从而导致派生类的析构函数未被调用,导致溢出。
(2)指针引发的程序崩溃:
a.使用迷途指针(悬空指针);
b.重复删除同一指针;
c.浅拷贝引起的重复释放同一片内存。
34.a和b值交换
(1)不考虑和值越界:
a=a+b;
b=a-b;
a=a-b;
(2)考虑和值越界:
a=a^b;
b=a^b;
a=a^b;
35.内存中的数据对齐
定义:
数据所在物理内存地址必须是数据长度的整数倍,WORD数据(2字节短数据:
short)的内存地址要被2整除,DWORD数据(4字节长数据:
int)的内存地址要被4整除。
注:
a.1word=2byte=16bit;
b.#pragmapack可用来自定义对齐大小。
1.限定补齐与默认补齐
2.结构体数据补齐3.联合体数据补齐(最大数据的整数倍)
4.为什么需要进行数据补齐?
这样有助于加快计算机的读取速度,否则就得多花指令周期了。
为此,编译器默认会对结构体进行处理(实际上其它地方的数据变量也是如此),让宽度为2的基本数据类型(short等)都位于能被2整除的地址上,让宽度为4的基本数据类型(int等)都位于能被4整除的地址上。
二、类
1.类的三大特征
封装(安全性):
(7)是对客观事物的抽象过程,并对数据(属性)和方法(操作)进行保护,提升安全性;
(8)隐藏内部“实现”细节,因此只需通过“接口”对数据进行访问;
(9)增强代码的可维护性;
(10)代码重用。
继承性:
(1)接口继承、实现继承、可视继承;
(2)可以获取基类的数据和接口,并对原先没有的成分进行扩展;
(3)代码重用(含有重载);
多态性:
(1)一个接口,多种方法;
(2)是将基类设置为一个或者多个派生类相等的技术:
即将派生类类型的指针传递给基类类型的指针,并根据派生类指针类型及虚函数在运行时刻接口选择,实现动态联编;
(3)接口重用(覆盖);
2.类的访问权限和继承关系:
说明:
“类成员”是指“类内代码”,“用户代码”是指“类外代码”。
(1)单类中的访问权限
类内代码:
1.可访问public、private、protected成员变量;
类外代码:
1.只可访问public成员变量;
2.不可访问private和protected成员变量。
(2)派生类中的访问权限
类内代码:
1.派生类内部代码可访问基类的public及protected成员变量;
2.无法访问private成员变量。
类外代码:
Public成员
Private成员
Protected成员
公有继承
Y
N
N
私有继承
N
N
N
保护继承
N
N
N
注:
可利用成员函数对protected成员进行间接访问。
3.类的构造函数、析构函数、复制构造函数、赋值操作函数
4.继承时的构造函数执行顺序
(1)普通继承
先执行基类的构造函数,再执行派生类成员对象的构造函数,最后执行派生类自身的构造函数。
(2)虚继承(防止产生二义性):
虚基类只被构造一次
5.虚继承与虚函数继承的sizeof()问题
虚继承:
基类与派生类分别拥有一个虚表指针(如果二者分别含有虚函数的话),并含有虚继承的虚表指针;
非虚继承:
基类与派生类共用一个虚表指针(如果二者之一含有虚函数的话);
(1)虚继承(消除二义性)与虚函数继承
二者结果相同:
原因:
1.B和C都虚继承了A,因此二者与A不共享虚指针(虚地址或虚表);
2.
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 大学 期末考试 计算机 面试 笔试 知识