2022年C++面试题汇总 .pdf
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_05.gif)
《2022年C++面试题汇总 .pdf》由会员分享,可在线阅读,更多相关《2022年C++面试题汇总 .pdf(13页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、C+知识点整理空指针与野指针的区别:空指针也就是通常指向为NULL 的指针, 野指针就是指向一块未知的内存区域 (可以是通过malloc 或 new 申请空间后,释放后没有将指针置为空),也有可能定义了一个指针没有初始化,由于内存空间中的值在未赋值之前是随机数,所以也有可能诞生野指针。malloc 函数为 C 语言中的标准函数, 标准中规定:在分配内存失败时会返回“ NULL Pointer”空指针,而非为初始化的指针。C+在分配内存失败时会抛出BAD_ALLOC异常。野指针:指向垃圾内存的指针,而非空指针。野指针产生原因:1.声明的指针未被初始化,指针默认值随机产生。创建指针应该将其初始化为
2、NULL 或者指向某一内存。2.free 和 delete 掉的指针未重置为NULL ,free 后的指针仍指向该内存,但该内存已变为垃圾内存。另:空指针不指向任何实际的对象或函数,反过来说对象或函数的指针也不可能为空指针。, auto 是默认类型, 每次调用sum 函数时 auto 类型的变量重新赋值为0, static 是静态变量,如果在函数内部进行定义,则只在第一次调用时进行赋初值,其作用范围是sum 函数内部,在函数内部可以改静态变量的值;先说宏和函数的区别:1. 宏做的是简单的字符串替换(注意是字符串的替换,不是其他类型参数的替换),而函数的参数的传递 ,参数是有数据类型的,可以是各
3、种各样的类型. 2. 宏的参数替换是不经计算而直接处理的,而函数调用是将实参的值传递给形参,既然说是值,自然是计算得来的. 3. 宏在编译之前进行,即先用宏体替换宏名,然后再编译的 ,而函数显然是编译之后,在执行时 ,才调用的 .因此 ,宏占用的是编译的时间,而函数占用的是执行时的时间. 4. 宏的参数是不占内存空间的,因为只是做字符串的替换,而函数调用时的参数传递则是具体变量之间的信息传递,形参作为函数的局部变量,显然是占用内存的. 5. 函数的调用是需要付出一定的时空开销的,因为系统在调用函数时,要保留现场 ,然后转入被调用函数去执行,调用完 ,再返回主调函数,此时再恢复现场,这些操作 ,
4、显然在宏中是没有的. 内联函数与宏的区别:1.内联函数在运行时可调试,而宏定义不可以; 2.编译器会对内联函数的参数类型做安全检查或自动类型转换(同普通函数),而宏定义则不会;3.内联函数可以访问类的成员变量,宏定义则不能;4.在类中声明同时定义的成员函数,自动转化为内联函数。external 作用之一: 当它与“ C” 一起连用时, 如:extern “ C” void fun(int a , int b);会告诉 C+编译器在编译fun 这个函数名是按着C 的规则去翻译相应的函数名而不是C+的,C+的规名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - -
5、 - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 13 页 - - - - - - - - - 则在翻译这个函数名时会把fun 这个名字变得面目全非。 。回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方法直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应回调函数不能是特定的类成员函数。因为类成员函数含有this 指针。核心就是类成员函数需要this 指针访问函数,而全局或者静态函数不需要this
6、指针。简言之,类的成员函数需要隐含的this 指针 而回调函数没有办法提供。int *a34, 则变量占有的内存空间为每个元素存放的都是二级指针,每个指针在32 位系统下占 4 个字节的内存,共 3*4=12 个元素,则共占内存12*4=48 字节C+中使用模板类的原因:(1) 可用来创建动态增长和减小的数据结构;(2) 它是类型无关的,因此具有很高的可利用性;(3) 它在编译时检查数据类型,保证了类型安全;(4) 它是平台无关的,具有可移植性;(5) 可用于基本数据类型。A.由于编译后的名字不同,C+程序不能直接调用C 函数B.extern C 既可以修饰函数也可以修饰变量C.c+提供关键字
7、extern“ C”,被 extern C修饰的是按照C 语言方式编译和连接的它是 if not define 的简写, 是宏定义的一种, 实际上确切的说, 这应该是预处理功能三种(宏定义、文件包含、条件编译)中的一种-条件编译。在 c语言中,对同一个变量或者函数进行多次声明是不会报错的。所以如果h 文件里只是进行了声明工作,即使不使用# ifndef 宏定义,多个c 文件包含同一个h 文件也不会报错。但是在 c+语言中,#ifdef 的作用域只是在单个文件中。所以如果h 文件里定义了全局变量,即使采用 #ifdef 宏定义,多个c 文件包含同一个h 文件还是会出现全局变量重定义的错误。使用
8、#ifndef 可以避免下面这种错误:如果在h 文件中定义了全局变量,一个c 文件包含同一个 h 文件多次, 如果不加 #ifndef 宏定义,会出现变量重复定义的错误;如果加了 #ifndef,则不会出现这种错误。根据语言定义 , 在指针上下文中的常数0 会在编译时转换为空指针。也就是说, 在初始化、赋值或比较的时候, 如果一边是指针类型的值或表达式, 编译器可以确定另一边的常数0 为空指针并生成正确的空指针值。因此下边的代码段完全合法:char *p = 0; if(p != 0) 然而 , 传入函数的参数不一定被当作指针环境, 因而编译器可能不能识别未加修饰的0 “ 表名师资料总结 -
9、- -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 13 页 - - - - - - - - - 示” 指针。在函数调用的上下文中生成空指针需要明确的类型转换,强制把 0 看作指针。例如 , Unix 系统调用execl 接受变长的以空指针结束的字符指针参数。它应该如下正确调用:execl(/bin/sh, sh, -c, date, (char *)0); 如果省略最后一个参数的(char *) 转换 , 则编译器无从知道这是一个空指针,从而当作一个0 传入。 (注意很多Unix 手册在这个
10、例子上都弄错了。) 堆和栈A.堆的大小仅受操作系统的限制,栈的大小一般一般较小B.在堆上频繁的调用new/delete 容易产生内存碎片,栈没有这个问题A.堆和栈都可以动态分配所谓动态内存分配就是指在程序运行的过程中动态地分配或者回收存储空间的分配内存的方法。动态内存分配不象数组等静态内存分配方法那样需要预先分配存储空间,而是由系统根据程序的需要即时分配,且分配的大小就是程序要求的大小。从以上动、静态内存分配比较可以知道动态内存分配相对于静态内存分配的特点:1、不需要预先分配存储空间;2、分配的空间可以根据程序的需要扩大或缩小。一是时间不同。静态分配发生在程序编译和连接的时候。动态分配则发生在
11、程序调入和执行的时候。二是空间不同 。堆都是动态分配的,没有静态分配的堆。栈有 2 种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由函数alloca()进行分配。 不过栈的动态分配和堆不同,他的动态分配是由编译器进行释放,无需我们手工实现。对于一个进程的内存空间而言,可以在逻辑上分成3 个部份: 代码区 ,静态数据区 和动态数据区 。动态数据区一般就是“ 堆栈 ” 。“ 栈(stack) ”和“ 堆(heap) ” 是两种不同的动态数据区,栈是一种线性结构,堆是一种链式结构。进程的每个线程都有私有的“ 栈” ,所以每个线程虽然代码一样,但本地变量的数据都是
12、互不干扰。一个堆栈可以通过“ 基地址 ” 和“ 栈顶 ” 地址来描述。全局变量和静态变量分配在静态数据区,本地变量分配在动态数据区,即堆栈中。 程序通过堆栈的基地址和偏移量来访问本地变量。一般,用 static 修饰的变量,全局变量位于静态数据区。函数调用过程中的参数,返回地址, EBP 和局部变量都采用栈的方式存放。内存管理常用区间和区间中的数据静态区 (static): 存放(初始化的)全局变量、静态变量和(未初始化的 )全局变量和静态变量;栈区 (stack): 存放局部变量和函数的形参。栈中的内存空间由编译器自动申请和释放。堆区 (heap): 存放动态分配内存函数申请的变量。堆中的内
13、存空间需要程序员手动释放,否则会引发内存泄露。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 13 页 - - - - - - - - - 5. 分配效率:栈的效率比较高。堆的效率比栈要低得多。6. 增长方向:堆的增长方向是从程序低地址到高地址向上增长,而栈的增长方向刚好相反(实际情况可能不是这样的,与CPU 的体系结构有关)堆是不连续的, 生长方向是向上的,即向着内存地址增大的方向增长;栈是连续的,生长方向是向下的,即向着内存地址减小的方向增长。栈: 在 Windows
14、 下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS 下,栈的大小是2M(也有的说是1M ,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow 。因此,能从栈获得的空间较小。堆:堆是向高地址扩展的数据结构, 是不连续的内存区域。这是由于系统是用链表 来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。阐述 C+ STL 中 vector ,set,multiset,list,map,multimap,deque 的特点 .vector 和 built-i
15、n 数组类似,它拥有一段连续的内存空间,并且起始地址不变,因此它能非常好的支持随即存取,即 操作符,但由于它的内存空间是连续的,所以在中间进行插入和删除会造成内存块的拷贝,另外,当该数组后的内存空间不够时,需要重新申请一块足够大的内存并进行内存的拷贝。这些都大大影响了vector 的效率。list 就是 数据结构 中的双向链表 (根据 sgi stl 源代码 ),因此它的内存空间可以是不连续的,通过指针来进行数据的访问,这个特点使得它的随即存取变的非常没有效率,因此它没有提供 操作符的重载。但由于链表的特点,它可以以很好的效率支持任意地方的删除和插入。deque是一个 double-ended
16、 queue,它的具体实现不太清楚,但知道它具有以下两个特点:它支持 操作符,也就是支持随即存取,并且和vector 的效率相差无几,它支持在两端的操作: push_back,push_front,pop_back,pop_front 等,并且在两端操作上与list 的效率也差不多。Map 是 STL 的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在 map 中出现一次, 第二个可能称为该关键字的值)的数据处理能力, 由于这个特性map内部的实现自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能。set是集合, set 中不会包含重复的元素,
17、这是和vector 的第一个区别,第二个区别是set内部用平衡二叉树实现,便于元素查找,而vector 是使用连续内存存储,便于随机存取。因此在实际使用时,如何选择这几个容器中哪一个,应根据你的需要而定,一般应遵循下面名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 13 页 - - - - - - - - - 的原则:1、如果你需要高效的随即存取,而不在乎插入和删除的效率,使用vector 2、如果你需要大量的插入和删除,而不关心随即存取,则应使用list 3、如果你需要
18、随即存取,而且关心两端数据的插入和删除,则应使用deque。4、如果你要存储一个数据字典,并要求方便地根据key 找 value,那么 map 是较好的选择5、如果你要查找一个元素是否在某集合内存中,则使用set存储这个集合比较好vector, 译为“ 向量 ” , 可以理解为线性代数中的向量,也可以理解为动态数组。为了实现动态,有的编译器会默认为vector 生成一个长度,当插入的元素的个数大于该长度时,就会生成一个长度为原长度二倍的数组,并将原来数组的数据拷贝在新数组中。插入操作的平均复杂度为O(1). 因此,插入操作有可能使前面获取的迭代器失效。deque, 有双向 (de)队列 (qu
19、eue)的意味,是可实现双向插入数据的动态数组。为了实现双向插入的功能,编译器一般会把其数据结构设置成一段一段的数组,每段数组链接起来构成一个超级大链表,然后为之重载数组的接口。如果前面的数组填满了,就会在大链表的前面生成一段数组,如果后面的数组填满了,也一样。因此,插入操作一般不会影响前面获取的迭代器。list: 双向链表。有的编译器底层用环形链表来实现的。插入操作一般不会影响已获取的迭代器。set, multiset: 分别实现的是无重复元素的集合和有重复元素的集合。一般由红黑树实现map,multimap : 分别实现的是无重复元素的映射关系,和有重复元素的映射关系。一般由红黑树实现。进
20、程和线程1.定义进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位. 线程是进程的一个实体,是 CPU 调度和分派的基本单位,它是比进程更小的能独立运行的基本单位 .线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源. 2.关系一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行. 相对进程而言, 线程是一个更加接近于执行体的概念,它可以与同进程中的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。3.区别进程
21、和线程的主要差别在于它们是不同的操作系统 资源管理方式。进程有独立的地址空间,名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 13 页 - - - - - - - - - 一个进程崩溃后, 在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。 线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变
22、量的并发操作,只能用线程,不能用进程。1) 简而言之 ,一个程序至少有一个进程,一个进程至少有一个线程.2) 线程的划分尺度小于进程,使得多线程程序的并发性高。3) 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。4) 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。5) 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 2022年C+面试题汇总 2022 C+ 试题 汇总
![提示](https://www.taowenge.com/images/bang_tan.gif)
限制150内