2021春招整理c++

1.重写和重载

重写就是指派生类中覆盖基类中的同名函数,重写就是重写函数体,要求基类函数必须是虚函数的。就是与基类的虚函数有相同的参数个数,相同的参数类型,返回值也要相同.
重载就是同一范围定义中的同名成员函数才存在重载关系。主要特点是函数名相同,参数类型和数目有所不同来区分的函数,重载和函数成员是否是虚函数无关。

2.多态是什么

多态就是不同继承关系的类对象,去调同一函数,产生了不同的行为。

3. 基类的析造函数定义为虚函数

在用基类操作派生类时,为了防止执行基类的虚构函数,不执行派生类的析构函数,这样的删除只能删除基类对象,而不能删除子类对象,形成了删除一半对象,会造成资源泄露。

4.内存泄露是什么?

c++中内存泄露又称为堆内存泄露,堆内存是指程序从堆中分配的,大小任意的可以在程序运行期决定内存块,使用完后必须显式的释放的内存。应用程序一般使用malloc和new等函数从堆中分配到块内存。使用完后,程序必须负责相应的调用free或delete释放该内存块,否则,这块内存就不能被再次使用,我们称这块内存泄露了。

5. 内存泄漏解决方法:

计数法,使用new或者malloc时,delete或free时,该数减一。程序执行完后,程序执行完打印这个计数,如果不为0则表示存在内存泄露。(智能指针)
一定要将基类的析构函数声明为虚函数
对象数组的释放一定要用delete []
有new就有delete,有malloc就有free,保证它们一定成对出现

6.Volatile关键字的作用:

(1)Volatile关键是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素修改。
(2)volatile定义变量的值是易变的,每次用到这个变量的值的时候都要去重新读取这个变量的值,而不是读寄存器内的备份。多线程中被几个任务共享的变量需要定义为volatile类型。

7. c++多态的机制

8. static关键字(重点)

(1)修饰全局变量时,表明一个全局变量只对当前文件中可见,也就是说可以定义一个其名字相同的变量了。
(2)修饰局部变量时,表明该变量的值不会因为函数中止而丢失。静态局部变量即使在声明时未赋初值,编译器也会把它初始化为0.
(3)修饰函数时,表明该函数只在同一文件中调用,其他文件不能引用该函数。其他文件可以定义同名函数,互不影响
(4)面向对象
①在类中数据成员的声明前加上static关键字,该数据成员就是类中的静态数据成员。
1)静态数据成员存储在全局数据区,静态数据成员在定义时分配存储空间,所以不能在类声明中定义。
2)静态数据成员是类的成员,无论定义多少个类的对象,静态数据成员的拷贝只有一个,且对该类的所有对象可见。也就是说任一对象都可以对静态数据成员进行操作。
②静态成员函数
1)与静态数据成员类似,静态成员函数属于整个类,而不是某一个对象。
a.静态成员函数没有this指针,他无法访问类对象的非静态数据成员,也无法访问非静态成员函数,他只能调用其余的静态成员函数。
b.出现在类体外的函数定义不能指定关键字static.。
c.非静态成员函数可以任意访问静态成员函数和静态数据成员。

9. const关键字(重点)

(1)Const修饰普通变量:修饰的变量不可变
(2)const修饰指针:分为指针常量和常量指针
①指针常量(底层指针):指向一个只读变量,表示指向的变量不可变。
②常量指针(顶层指针):指的是指针,表示指针是个常量,不能改变指向。
(3)在函数声明时:
①const可以修饰形参,表明他是一个输入参数,在函数内部不能改变其值。
②Const修饰函数返回值,
③对于类
1)Const修饰成员变量,表示成员不能被修改,同时它只能在初始化列表中赋值。
2)const修饰成员函数,则该成员函数不能修改类中任何非const成员函数。一般写在函数的最后来修饰。
3)对于const类对象/指针/引用,只能调用类的const成员函数,因此,const修饰成员函数的最重要作用就是限制对于const对象的使用。

10.宏定义

11. 内联函数

12.内联函数与宏定义的区别

13. new和malloc的区别

(1)New delete是运算符,malloc和free是库函数
(2)New 是类型安全的,而malloc不是
(3)New自动分配要计算的空间大小,malloc需要手动计算
(4)New 的实现过程是:首先调用operator new的标准库函数,分配足够大的原始为类型化的内存,以保存指定类型的一个构造函数,用指定初始化构造对象;最后返回新分配并构造后的对象的指针。 malloc仅仅分配内存空间。Free仅仅回收内存空间。
(5)New和delete返回的是具体类型的指针。Malloc和free返回的是void类型的指针。

14. 虚函数表

15. 简要说说c++的内存分区

(1)栈:主要存放函数内局部变量和存储单元都可以在栈上创建。
(2)堆:主要存放new分配的内存块,如果内存块程序员没有释放掉,那么在程序结束后,操作系统会自动回收。
(3)静态/全局存储区:全局变量和静态变量被分配到同一块内存中
(4)常量区这里面存放的是常量,不允许修改
(5)代码区:存放函数体的二进制代码

16. 智能指针

智能指针是一个类,用来存储指向动态分配对象的指针,负责自动释放动态分配的对象,防止堆内存泄露。动态分配的资源,交给一个类去管理,当类对象声明结束时,自动调用析构函数释放资源。
1.shared_ptr:实现原理:采用引用计数器的方法,允许多个智能指针指向同一对象,每当多一个指针指向该对象时,指向该对象的所有智能指针内部引用计数+1,每当减少一个智能指针指向对象时,引用计数会减1,当计数为0时,会自动释放动态内存的资源。 (实现见算法篇)
2. unique_ptr:采用的是独享所有权主义,一个非空的unique_ptr总是拥有它所指向的资源,转移一个unique_ptr将会把所有权转移给目标指针,源指针被置空;所以unique_ptr不支持普通的拷贝和赋值操作,不能用在STL的标准容器中;局部变量的返回值除外,如果你拷贝一个unique_ptr,那么拷贝结束后,这两个unique_ptr都会指向相同的资源,造成在结束时对同一内存指针多次释放而导致程序崩溃。
3. weak_ptr:弱引用,引用计数有一个问题就是互相引用形成环,这样两个指针指向的内存都无法释放,需要使用weak_ptr来打破环型引用。他指向一个由shared_ptr管理的对象而不影响所指对象的生命周期,也就是说,他只引用,不计数,如果一块内存被shared_ptr和weak_ptr同时引用,当所有shared_ptr析构之后,不管还有没有weak_ptr引用该内存,内存都会被释放。所以weak_ptr不保证他指向的内存一定是有效的,在使用之前使用函数lock()检查weak_Ptr是否为空指针。

17. 虚表(重点)

(1)虚表:虚函数表的缩写类中含有virtual关键字修饰的方法时,编译器会自动生成虚表
(2)虚表指针:在含有虚函数的类实例化对象时,对象地址的前四个字节存储的指向虚表的指针
1)编译器在发现基类中有虚函数时,会自动为每个含有虚函数的类生成一份虚表,该表是一个一维数组,虚表里保存了虚函数的入口地址
2)编译器会在每个对象的前四个字节中保存一个虚表指针,即vptr,指向对象所属类的虚表。在构造时,根据对象的类型去初始化虚指针vptr,从而让vptr指向正确的虚表,从而在调用虚函数时,能找到正确的函数
3)所谓的合适时机,在派生类定义对象时,程序运行会自动调用构造函数,在构造函数中创建虚表并对虚表初始化。在构造子类对象时,会先调用父类的构造函数,此时,编译器只“看到了”父类,并为父类对象初始化虚表指针,令它指向父类的虚表;当调用子类的构造函数时,为子类对象初始化虚表指针,令它指向子类的虚表
4)当派生类对基类的虚函数没有重写时,派生类的虚表指针指向的是基类的虚表;当派生类对基类的虚函数重写时,派生类的虚表指针指向的是自身的虚表;当派生类中有自己的虚函数时,在自己的虚表中将此虚函数地址添加在后面,
这样指向派生类的基类指针在运行时,就可以根据派生类对虚函数重写情况动态的进行调用,从而实现多态性。

18. STL底层实现

  1. vector 底层数据结构为数组 ,支持快速随机访问
  2. list 底层数据结构为双向链表,支持快速增删
  3. deque 底层数据结构为一个中央控制器和多个缓冲区,支持首尾(中间不能)快速增删,也支持随机访问 。 deque是一个双端队列(double-ended queue),
  4. stack 底层一般用list或deque实现,封闭头部即可,不用vector的原因应该是容量大小有限制,扩容耗时
  5. queue 底层一般用list或deque实现,封闭头部即可,不用vector的原因应该是容量大小有限制,扩容耗时(stack和queue其实是适配器,而不叫容器,因为是对容器的再封装)
  6. priority_queue 的底层数据结构一般为vector为底层容器,堆heap为处理规则来管理底层容器实现
  7. set 底层数据结构为红黑树,有序,不重复
  8. multiset 底层数据结构为红黑树,有序,可重复
  9. map 底层数据结构为红黑树,有序,不重复
  10. multimap 底层数据结构为红黑树,有序,可重复
  11. unordered_set 底层数据结构为hash表,无序,不重复
  12. unordered_multiset 底层数据结构为hash表,无序,可重复容器
  13. unordered_map 底层数据结构为hash表,无序,不重复
  14. unordered_multimap 底层数据结构为hash表,无序,可重复

19. map和set

  1. 他们的底层都是以红黑树的结构实现,因此插入删除等操作都在O(logn)时间内完成,因此可以完成高效的插入删除;
  2. set所有元素只有key,value就是key。而map所有元素都是key加value值实现的,map的键是不能修改的,但是他的值是可以修改的。
  3. 因为map和set要求是自动排序的,红黑树能够实现这一功能,而且时间复杂度比较低。

20.20.c++从cpp文件到exe可执行文件经历的流程

预处理阶段:处理以 # 开头的预处理命令; .c–>.i
编译阶段:翻译成汇编文件; .i->.s
汇编阶段:将汇编文件翻译成可重定位目标文件: .s->.o
链接阶段:将可重定位目标文件和 printf.o 等单独预编译好的目标文件进行合并,得到最终的可执行目标文件 结合生成可执行目标程序。

21.c++动态链接和静态链接的比较

  1. 静态编译,编译器在编译可执行文件时,把需要用到的对应动态链接库中的部分提取出来,连接到可执行文件中去,使可执行文件在运行时不需要依赖于动态链接库;
  2. 动态编译的可执行文件需要附带一个动态链接库,在执行时,需要调用其对应动态链接库的命令。所以其优点一方面是缩小了执行文件本身的体积,另一方面是加快了编译速度,节省了系统资源。缺点是哪怕是很简单的程序,只用到了链接库的一两条命令,也需要附带一个相对庞大的链接库;二是如果其他计算机上没有安装对应的运行库,则用动态编译的可执行文件就不能运行。

23.有没有了解过拷贝构造函数?

1>拷贝构造函数是一种特殊的构造函数,函数的名称必须和类名称一致,它必须的一个参数是本类型的一个引用变量。
2>拷贝构造函数的调用时机
(1)对象以值传递的方式传入函数参数。
(2)对象以值传递的方式从函数返回。
(3)对象需要通过另外一个对象进行初始化。

24.内存分配方式一般有哪些?

1.从静态存储区域分配,内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。
2.在栈上创建,在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数在执行结束时,这些存储单元被自动释放。
3.从堆上分配,亦是动态分配。

25. 堆和栈的差别?

  1. 分配方式不同,堆内存由程序员手动释放,栈由系统自动分配

26.C++面向对象的三个特性和五个原则

三个特性:
1 继承:指可以让某个类型的对象获得另一个类型的对象的属性的方法。
2 封装:就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的隐藏。
3 多态:
五大原则:
单一职责原则SRP,开放封闭原则OCP,里氏替换原则LSP,依赖倒置原则DIP,接口分离原则ISP。

27.什么是内存池

(1)内存池是一种内存分配的方式,通常我们习惯直接用new,malloc等申请内存,这样做的缺点在于由于所申请的内存块的大小不定,当频繁使用时会造成大量的内存碎片,进而降低性能。内存池在真正使用之前,先申请分配一定数量的,大小相等的内存块留作备用,当有新的内存需求时,就从内存池中分出一部分内存块,若内存块不够再继续申请新的内存。这样做的好处就是避免了内存碎片,内存分配效率得到提升。

28.哈希冲突的解决方法。

(1)什么是哈希冲突?
由于哈希算法的计算的数据是无线的,而计算后的结果范围有限,因此总会存在不同的数据经过计算后得到的值相同,这就是哈希冲突。
(2)解决方法:
①建立公共溢出区
一旦hash函数计算的结果相同,就放入公共溢出区
②线性探测法
使用hash函数计算的位置如果已经有元素占用了,则向后依次寻找,找到表尾则回到表头,直到找到一个空位。
③平方探测法
从发生冲突的单元加上12,22,32,…,n2,直到遇到空闲的单元
④开链法
每个表格维护一个list,如果hash函数计算出的格子相同,则按照顺序存放在这个list中。
⑤再散列法
发生冲突时使用另一种hash函数再计算一个地址,直到不冲突

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值