C++面试知识点汇总

C++面试知识点汇总

  本博文是本文历时3个月,收集各种资料,汇总的C++面试题,欢迎各位博友评价。

1.C/C++内存有哪几种类型

  C中内存分为5个区:堆(malloc),栈(如:局部变量,函数参数),程序代码区(存放二进制代码),全局/静态存储区(全局变量,static变量)和常量存储区(常量)。
  全局变量/static变量会初始化为零,而堆和栈上的变量是随机的,不确定的。

  • 堆:用于程序内存动态分配,用C/C++中的new/malloc分配,delete/free释放,堆是C/C++函数库提供的;
  • 栈:在程序运行中,局部作用域出现的一些局部变量可以在栈上创建,等脱离该作用域创建的内存被释放;
  • 全局/静态存储区:这块内存在程序编译期间已经分配好,在程序整个运行阶段一直存在;
  • 常量存储区:特殊的一块内存,里面存放的常量,不允许修改。

2.堆内存、栈内存的对比:

  1. 栈内存 存储的是局部变量,而堆内存存储的是实体;
  2. 栈内存的更新速度要快于堆内存,因为局部变量的生命周期很短;
  3. 栈内存存放的变量生命周期一旦结束就会被释放,而堆内存存放的实体会被垃圾回收机制不定时的回收。

3.堆和自由存储区的区别

  总得来说,堆是C语言和操作系统的术语,是操作系统维护的一块动态分配的内存;自由存储是C++中通过new与delete动态分配和释放的抽象概念,他们并不完全一样。
  直接的说:堆用来存放动态分配的对象,通过malloc创建,free释放;而自由存储区是C++中通过new和delete动态分配和释放对象的抽象概念。
  通过new来申请的内存区域可称为自由存储区。

4.程序编译的过程

在这里插入图片描述1)预处理:对所有的define进行宏替换,处理所有的条件编译#idef等; 处理#include指令;删除注释等。
2)编译:将预处理后的文件进行词法分析,语法分析,语义分析以及优化相应的汇编文件。
3)优化
4)汇编:将汇编文件转化与机器能执行的文件
5)链接:包括地址和空间分配,符号决议和重定位。

5.什么是内存泄漏?面对内存泄漏和指针越界,你有哪些方法?你通常采用哪些方法来避免和减少这类错误?

  用动态存储分配函数动态开辟的空间,使用完毕后未释放,结果导致一直占据该内存单元,即为内存泄露。
  采用以下方法:
1)使用的时候要记得指针的长度;
2)malloc的时候得确定在哪里free;
3)对指针赋值的时候应该注意被赋值指针需要不需要释放;
4)动态分配内存的指针最好不要再次赋值;
5)在C++中应该优先考虑使用智能指针。

6.哈希表的构造方法及解决冲突的方法

构造方法:
1)数字分析法;
2)平方取中法;
3)分段叠加法;
4)除留余数法 ;
5)随机数法;
处理冲突的方法:
1)开放地址法;
2)再哈希法;
3)拉链法;
4)建立公共溢出区;

7.const 有什么用途?

1)定义只读变量,或者常量;
2)修饰函数的参数和函数的返回值;
3)修饰函数的定义体,这里的函数为类的成员函数,被const修饰的成员函数代表不能修改成员变量的值,因此const成员函数只能调用const成员函数。
4)只读对象,只读对象只能调用const成员函数。

8.在C中用const能定义真正意义上的常量吗?C++中的const呢?

  在C中不能定义真正意义上的常量,因为C中的const仅仅从编译层来限定,不允许对const变量进行赋值操作,在运行期是无效的,所以并非真正的常量(比如:可以通过指针对const变量进行修改)。但是在C++中是有区别的,C++在编译时会把const常量加入符号表,以后(仍然在编译期)遇到这个变量会从符号中查找,所以C++中是不可能修改到const变量的,是真正意义上的常量。

9.什么时候生成默认构造函数(无参构造函数)?什么时候生成默认拷贝构造函数?什么是深拷贝?什么是浅拷贝?默认拷贝构造函数是哪些拷贝?什么时候用深拷贝?

1)没有任何构造函数时,编译器会自动生成默认构造函数,也就是无参构造函数;当类没有拷贝构造函数时,会生成默认拷贝构造函数。
2)深拷贝是指拷贝后对象的逻辑状态相同,而浅拷贝是指拷贝后对象的物理状态相同,默认拷贝构造函数为浅拷贝。
3)当系统中有成员指代了系统中的资源时,需要深拷贝。比如:指向了动态内存空间,打开了外存中的文件或者使用了系统中的网格接口等。如果不进行深拷贝,比如:动态内存空间,可能会出现多次被释放的问题。是否需要定义拷贝构造函数的原则是:类中是否有成员调用了系统资源,如果定义,那么拷贝构造函数一定是深拷贝;否则,没有意义。

10.C++中的类与C语言中struct的区别?

1)C++中的类默认的成员是私有的,struct默认的是公有的;
2)C++中的类可以定义成员函数,struct只能定义成员变量。

11.程序什么时候使用线程?什么时候单线程效率高?

1)耗时的操作使用线程,提高应用程序响应;
2)并行操作时使用线程,如:C/S架构的服务器并发线程响应用户的请求;
3)多CPU系统中,使用线程提高CPU的利用率;
4)改善程序结构,一个时长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样程序会利于理解和修改。

12.const 与define的区别:

区别constdefine
编译方式编译时确定其值预处理时进行替换
类型检查有数据类型,编译时进行数据的检查无类型,也不做类型检查
内存空间在静态存储区存储,仅此一份在代码段区,每做一次替换就会进行一次拷贝
防重复可防止重复定义不行

13.指针和引用的区别

区别指针引用
本质一个变量,存储内容为一个地址已有对象的别名
内存空间为实体,分配内存空间别名,不分配内存空间
存在多级有多级指针无多级引用
自增运行结果不 同
访问类型间接访问直接访问
初始化不用初始化需先初始化

14.指针与数组的区别

1)数组对应一块内存,而指针指向一块内存。
2)数组的地址和空间大小在生命周期不会发生改变(内容可能发生改变);指针指向的内存大小可以随时发生改变,当指针指向常量字符串时,它的内容不可以改变。
3)计算容量的区别:用sizeof计算数组的元素个数,无法计算指针所指向内存的大小;
4)数组名是常量指针,指针是变量指针。
5)对数组&和对指针&的意义不同,此时数组名不在当成指向一个元素的常量指针来使用。

15.函数指针与指针函数

函数指针:为指向函数的指针,是指针变量,他与函数名无关,只与参数列表和返回类型有关;
指针函数:本质是函数,返回值为一个指针。

16.请你谈谈map和set的区别,以及他们是怎么实现的?

  set是一种关联式容器,其特性如下:
1)set以RBTree作为底层窗口;
2)所有元素只有键没有值;
3)不允许出现键值重复;
4)所有的元素都会自动排序;
5)不能通过迭代器改变set的值,因为set的值就是健。
  map和set一样是关联式容器,它们的底层容器是红黑树,区别就在于map的值不作为键,键和值是分开的,它的特性如下:
1)map以RBTree作为底层容器;
2)所有的元素都是键+值存在;
3)不允许键重复;
4)所有的元素是通过键进行自动排序的;
5)map的键是不能修改的,但是其键对应的值是可以修改的。

17.理解list和vector的区别?

  vector拥有一段连续的内存空间,因此支持随机存取,如果需要高效的随机存取,而不在乎插入和删除的效率,使用vector;
  list拥有一段不连续的内存空间,因此不支持随机存取,如果需要大量的插入和删除,而不关心随机存取,则应使用。

18.static 关键字的作用?

1)作用域隐藏:当编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性,static可以用作函数和变量的前缀,对函数来讲,static的作用仅限于隐藏。
2)保持变量内容的持久:
3)默认初始化为0(static变量):
4)静态成员函数和静态成员变量是属于类的,所有对象只有一份拷贝。所以,不能将静态函数设置为虚函数。(虚函数是用来实现多态的,静态成员属于类而非对象,没有多态的概念)

19.请你简要说明C++和C的区别?

1)设计思想上:C++进面向对象的语言,而C是面向过程的结构化编程语言;
2)C++三大特性:C++具有封装,继承和多态三种特性;
3)增加许多类型安全的功能,比如:强制类型转换,C++支持范式编程,比如:模板类,函数模板等。

20.派生类和基类中有同名的函数,基类指针指向子类对象时,调用的函数是谁的?

  当基类指针指向一个子类对象,通过这个指针调用子类和基类同名成员函数的时候,基类声明为虚函数就会调子类的这个函数,不声明就会调用基类的。

21.STL是什么?STL容器有几种?

  STL(Standard template libaray,标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据算法的软件框架。STL的容器分为以下几个大类:
顺序容器、关联式容器、容器适配器
三种类型容器特性分别如下:

  1. 顺序容器: 容器并非排序的,元素的插入位置同元素的值无关,包含 vector、deque、list。
  • vector:动态数组, 元素在内存连续存放。随机存取任何元素都能在常数时间完成。在尾端增删元素具有较佳的性能。
  • deque:双向队列, 元素在内存连续存放。随机存取任何元素都能在常数时间完成(仅次于 vector )。在两端增删元素具有较佳的性能(大部分情况下是常数时间)。
  • list:双向链表, 元素在内存不连续存放。在任何位置增删元素都能在常数时间完成。不支持随机存取。
  1. 关联式容器:元素是排序的:插入任何元素,都按相应的排序规则来确定其位置;在查找时具有非常好的性能;通常以平衡二叉树的方式实现,包含:set、multiset、map、multimap。
  • set/multiset:set中不允许相同元素,multiset中允许存在相同元素;
  • map/multimap:map与set的不同在于map中存放的元素有且仅有两个成员变量,一个名为first,另一个名为second,map根据first值 对元素从小到大排序,并可快速地根据first来检索元素。map和multimap的不同在于是否允许相同first值元素。
  1. 容器适配器: 封装了一些基本的容器,使之具备了新的函数功能,包含 stack、queue、priority_queue。
  • stack:栈, 栈是项的有限序列,并满足序列中被删除、检索和修改的项只能是最近插入序列的项(栈顶的项),后进先出。
  • queue:队列, 插入只可以在尾部进行,删除、检索和修改只允许从头部进行,先进先出。
  • priority_queue:优先级队列, 内部维持某种有序,然后确保优先级最高的元素总是位于头部,最高优先级元素总是第一个出列。

22.malloc的原理?

  函数原型:void* malloc(size_t n)返回值类型为void* ,为动态分配得到的内存,但大小是确定的,不允许越界使用。
  malloc函数的实质体现在它有一个可以将可用内存块连接成一个长的列表的空闲链表,当调用malloc函数时,它沿着连接表寻找一个大到可以满足用户请求的内存块,将内存一分为二,将分配给用户的那块内存传给用户,剩下的那块返回连接表。

23.new 和 malloc的区别?

类型内容
属性new为关键字;malloc为库函数,需要头文件支持
参数使用new申请内存无需指定内存大小,编译器自行计算;而malloc需要显示给出所需内存的大小
返回类型new分配成功返回的是对象类型指针;malloc返回的void *
分配失败new分配失败,抛出bad_alloc异常;malloc则返回NULL
内存区域new分配的内存在自由存储区,malloc在堆上分配内存
  • 11
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值