day13
C++面试题
1.说一下常见的linux指令
ls:查看当前文件目录
cd:切换当前目录
rm:删除文件或者文件夹
cp:复制文件或者文件夹
cat:查看文件内容
touch:创建一个新文件
pwd:显示当前工作目录
2.请你说说delete和free的区别?
1.delete是运算符,free是库函数
2.delete在使用时会调用对象的析构函数,而free不会调用
3.delete用于释放new分配的空间,而free用于释放malloc分配的空间
4.调用free之前要检查被释放的指针是否为NULL,而delete不用
3.简述一下c++中的重载和重写?
重载:重载是函数名相同,函数中形参的个数、类型不同
重写:重写是派生类中的函数对基类中的虚函数进行重新定义
重载:重载就是不同的函数使用相同的函数名,但是函数中的形参的类型或者形参个数不同,调用的时候根据不同的形参来调用不同的函数,并且函数的重载根返回值没有关系。 并且重载用来实现静态多态
重写:重写就是派生类对基类中的虚函数重新实现。也就是函数名跟形参相同,只是函数的实现方式不同,重写用来实现动态多态。
4.简述一下面向对象的三大特征
面向对象的三大特征是封装,继承,和多态。封装就是隐藏函数内部实现的细节,只保留接口,这样用户在使用的时候,只需要调用不同的接口就可以,而不必知道函数内部实现的细节;继承,就是不同的类之间存在这样一种继承的关系,也就是子类可以继承父类的成员变量和成员函数;多态分为静态多态和动态多态,像重载就是静态多态,在编译时就确定了对象的状态,动态多态如函数的重写,子类通过对父类中的虚函数进行重写,可以实现不同的功能。
面向对象的三大特征就是封装、继承和多态。 封装就是将数据和操作数据的方法进行结合,隐藏对象的属性和实现细节,仅仅是公开对外的接口来和对象进行交互 继承,c++最重要的一个特征就是代码的重用性,通过继承机制,可以通过旧的数据类型来定义新的数据类型,新的类不仅拥有旧类的数据成员,而且还有属于自己的新的数据成员 多态是指通过基类的指针和引用,在运行时动态调用实际对象函数的行为。多态是在运行时根据基类的指针或者引用指向的对象来确定自己具体该调用哪一个类的虚函数,当父类指针指向父类对象时,就调用父类的虚函数;当父类指针指向子类对象时,就调用子类的虚函数
5.简述一下浅拷贝和深拷贝?
浅拷贝,将原对象的引用直接赋给新对象,新对象只是原对象的一个引用
深拷贝,创建一个新对象,将源对象的元素赋值给元对象,重新分配一个内存空间来存储原对象的元素
浅拷贝:浅拷贝又被称为值拷贝,把原对象的值拷贝到新对象当中去,如果元对象当中有指针并且在堆区中分配内存,使用浅拷贝的时候拷贝的是这个指针变量的数值,也就是说新对象和元对象指向的时同一块地址空间。
深拷贝,在拷贝的时候,会先开辟和原对象大小一致的内存空间,然后将元对象的数据拷贝到新对象当中去,这样元对象和新对象指向的是不同的内存空间,但是他们内部的内容是一致的,
6.简述一下c++中的多态?
c++中的多态指的是通过基类的指针或者引用,在运行时动态调用实际绑定对象函数的行为,多态分为动态多态和静态多态。静态多态指的是,在编译期间就确定该调用哪个函数,静态多态有函数的重载,运算符重载,泛型编程等;动态多态指的是在运行时,根据基类的指针或者引用,指向的对象来动态的决定该调用哪一个函数的行为,当父类指针指向父类对象时,就调用父类的虚函数;当父类指针指向子类对象时,就调用子类的虚函数 。
动态多态实现的原理,当类中声明一个虚函数时,编译器会在类中声明一个虚函数表,虚函数表会存储虚函数指针,虚函数表是由编译器自动生成和维护的,当存在虚函数时,每个对象都会存在一个指向虚函数表的指针,在多态调用时,这个指针就会根据这个对象在对应类的虚函数表中查找对应的函数,从而 调用这个函数。
7.简述一下虚函数的实现原理?
虚函数的作用主要就是实现动态多态,动态多态就是父类类型的指针指向子类的对象,然后通过父类的指针调用子类的成员函数,父类的指针也就有了多种形态,;
虚函数的实现原理,主要是通过虚函数表来实现的,当编译器处理虚函数时,会自动生成一个虚函数表,虚函数表中存储的是虚函数的地址,如果派生重写了父类的虚函数,那么派生类中的虚函数表中存储的就是派生类的虚函数地址,如果派生类没有重写基类的虚函数,那么派生类中存储的就是基类的虚函数地址,
8.什么是纯虚函数,有什么作用?
纯虚函数就是基类中的虚函数不能给出有意义的实现式,就可以把虚函数声明为纯虚函数,纯虚函数没有函数体,并且==0,纯虚函数的实现留给派生类去做,一个类中如果有纯虚函数,那么这个类就不能实例化对象,也被称作抽象类,
9.虚析构函数有什么作用?
虚析构函数主要是为了预防内存泄漏,将基类的析构函数声明为虚析构函数,如果没有声明为虚析构函数时,那么当基类的指针指向子类对象的时候,基类指针释放的时候就不会调用子类的析构函数,而是去调用父类的析构函数,这样的话,子类占用的内存空间就不会被释放掉,从而会造成内存泄漏
10.请你说说重载、复写、隐藏的区别?
重载:同一作用域下,函数名相同,函数的形参类型跟个数不相同,与返回值无关
复写:也就是重写,不同作用域下,函数名相同,实现不同
隐藏:不同作用域的同名函数构成隐藏
11.请你说说什么情况下会调用拷贝构造函数,什么时候会调用赋值操作?
调用拷贝构造函数的时机:用一个已经创建好的对象去初始化另一个对象,对象以值传递的方式传递给函数参数,
赋值操作的调用时机:将一个对象赋值给另一个对象
12.请你说说虚函数可以是内联函数吗?
1.虚函数可以是内联函数,内联是可以修饰虚函数的,但是当虚函数表现多态时不能内联函数。
2.内联函数实在编译器内联。而虚函数的多态在运行期间,编译器并不知道运行期会调用哪一个函数,因此虚函数表现为多态时不能内联
3。虚函数能够内联的情况就是,编译器在编译期时就知道调用哪个函数
13.请你说说虚函数和纯虚函数的区别?
1.他们的定义不同,虚函数是在函数返回值之前加上virtual,而纯虚函数没有函数体,并且==0;
2.虚函数有具体的实现,纯虚函数没有具体的实现,对于虚函数而言,父类和子类都有各自的版本,由多态的时候动态绑定;有纯虚函数的类被称为抽象类,不能够实例化对象
3.虚函数时c++中实现多态的机制,在很多情况下,如果在基类中不能对虚函数给出具体的实现,就把这个虚函数声明为纯虚函数,他的实现留给派生类去做
14.说一说STL中有哪些常见的容器?
1.顺序容器:容器并非排序的,元素的的插入位置和同元素的位置无关,包括vector,deque,list
2.关联性容器:元素是排序的,插入任何元素都按照插入顺序来确定其位置,包含set,multiset,map,multimap
3.容器适配器:封装了一些基本的容器,使之具备新的功能,stack,queue,
15.说一说vector跟list的区别?
1.底层实现不同,vector是数组,list是双向链表
2.是否支持随机访问,vector支持随机访问,list不支持随机访问
3.顺序内存,vector是顺序内存,list不是
16.简述一下vectory的实现原理?
vector是一种动态数组,在内存中具有连续的内存空间,支持快速随机访问,插入删除效率比较慢,并且当vector的大小和容量相等时,vector就需要扩容,vector扩容的过程,首先需要在内存中重新申请一块更大的内存,然后,将原内存空间的元素按照之前的顺序复制到新的内存空间中,然后再把之前的内存空间释放掉。
17.简述一下deque的实现原理?
deque是由一段一段定量的连续空间构成,支持双端插入数据,deque内部有一个map指针,分配空间比vector快,不需要重新拷贝
18.简述一下set的实现原理?
set是一种关联性容器,底层是用红黑树实现的,set容器中每一个元素就是二叉树的一个节点,set容器的删除和插入容器效率都比较高,是因为这些操作都只需要移动指针。set中的容器的元素都是唯一的,默认情况下会对元素进行升序排列,不会直接改变元素值,要改变元素值,必须先删除原来的元素,在插入新元素。
19.说一下红黑树的实现原理以及为什么要有红黑树?
1.红黑树具有平衡二叉树的特性
2.根节点是黑色的
3.每个叶子节点都是黑色的空节点,也就是说,叶子节点不存数据
4.任何相邻的节点都不能同时是红色,也就是说红节点是被黑节点隔开的
5.每个节点,从该节点到达其可达的叶子节点是所有路径,都包含相同数目的黑色节点
20.请说说c++中智能指针和指针的区别?
1.如果在程序中使用new从堆区分配内存,等到不需要时,就需要用delete来释放掉内存,c++中引入了智能指针来自动完成这个过程
2.智能指针和指针的区别:智能指针和普通指针的区别就是在于智能指针实际上就是给普通指针加上了一层封装机制,区别是他负责自动释放所指的对象,这样的一层封装机制就是为了让智能指针方便的管理一个对象的生命周期。指针是一种数据类型,而智能指针式一种类模板。
21.请你说说左值,右值,左值引用,右值引用?
1.左值,在c++中可以取地址的,有名字的就是左值, int a = 10;a就是左值
2.右值,不能取地址的,没有名字的就是右值,10就是右值
3.左值引用,就是对一个左值进行引用,将标识符关联到左值
4.右值引用,就是对一个右值进行引用,这种引用可以指向右值,但是不能对其运用地址运算符值包括字面常量(C-风格字符串除外,它表示地址)、诸如 x + y 等表达式以及返回值的函数(条件是该函数返回的不是引用),右值引用使用 && 声明
22.说一下c和c++中struct的区别以及class的区别?
结构体的区别:1.c的结构体不允许有函数存在,c++的结构体允许有内部成员函数存在,并且该函数可以是虚函数
2.c的结构体内部成员不允许加权限,默认是public,c++的结构体内部成员允许加权限,可以是public、private等
3.c的结构体不可以继承。而c++的结构体可以从其他结构体或者类继承
4.c的结构体不可以初始化数据成员,c++的结构体可以初始化数据成员
5.c中使用结构体需要加上struct关键字,c++中不需要加上struct关键字
结构体和class的区别:1.struct一般用于描述数据结构的集合,而clss是对一个对象数据的封装
2.访问权限不同,结构体默认访问权限是public,class默认访问权限是private
3.struct默认继承方式是public,而class默认继承方式是private
4.class可以用于定义模板参数,而结构体就不会
23.说一下什么是野指针,怎么避免野指针的产生?
野指针:野指针指向的位置是未知的,随机的,不正确的
产生原因:1.指针变量没有初始化或者随便赋值。
2.指针释放后没有置空
3.指针操作超出了变量的作用域
如何避免野指针:1.指针变量一定要初始化,可以置为NULL;
2.释放后置为NULL;
24.说说c语言和c++语言的区别?
1.c语言是面向过程的语言,而c++是面向对象的语言,c语言也没有面向对象的封装、继承、多态等行为,自然也不支持面向对象的一些语法。
2.c++支持函数的重载,c语言不支持。
3.C语言中struct不允许有函数,而c++中struct有函数
4.C 语言采用 malloc 和 free 函数动态申请和释放内存,而 C++ 使用 new 和 delete 运算符;
25.说说const和define的区别?
1.const在编译阶段调用,而const在预处理阶段调用
2.const只是简单的字符串替换,没有类型检查,而const需要类型检查
3。用define定义的变量不可以用指针去指向,而const定义的变量可以用指针去指向
4.define在内存中会有多个拷贝,而const在内存中只会有一个拷贝;
26.简述一下堆和栈的区别?
1.管理方式:对于栈的管理,是由编译器自动管理,无需手动控制;对于堆来说,分配和释放都是由程序员控制的。
2.空间大小,一般来说,栈的空间大小是要小于堆的,堆内存几乎没有什么限制,而栈内存是有一定的空间大小的
3.碎片问题,对于堆来讲,由于分配和释放是由程序员控制的(利用new/delete 或 malloc/free),频繁的操作势必会造成内存空间的不连续,从而造成大量的内存碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的数据结构,在某一数据弹出之前,它之前的所有数据都已经弹出。
new和malloc的区别?
1. new 的实现原理: 如果是简单类型,则直接调用 operator new(),在 operator new() 函数中会调用 malloc() 函数,如果调用 malloc() 失败会调用 _callnewh(),如果 _callnewh() 返回 0 则抛出 bac_alloc 异常,返回非零则继续分配内存。 如果是复杂类型,先调用 operator new()函数,然后在分配的内存上调用构造函数。 2. new 和 malloc 的区别 - new 是操作符,而 malloc 是函数; - 使用 new 操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算,而 malloc 则需要显式地指出所需内存的尺寸; - new 分配失败的时候会直接抛出异常,malloc 分配失败会返回 NULL; - 对于非简单类型,new 在分配内存后,会调用构造函数,而 malloc 不会; - new 分配成功后会返回对应类型的指针,而 malloc 分配成功后会返回 void * 类型; - malloc 可以分配任意字节,new 只能分配实例所占内存的整数倍数大小; - new 可以被重载,而 malloc 不能被重载; - new 操作符从自由存储区上分配内存空间,而 malloc 从堆上动态分配内存; - 使用 malloc 分配的内存后,如果在使用过程中发现内存不足,可以使用 realloc 函数进行内存重新分配实现内存的扩充,new 没有这样直观的配套设施来扩充内存。
请你说说 C 语言里面 volatile,可以和 const 同时使用吗?
voliatile限定符是用来告诉计算机,所修饰的变量的值随时都会进行修改的,用于防止编译器对该代码进行优化,通俗的讲就是编译器在用到这个变量时必须每次都小心地从内存中重新读取这个变量的值,而不是使用保存在寄存器里的备份。const 和 volatile 可以一起使用,volatile 的含义是防止编译器对该代码进行优化,这个值可能变掉的。而 const 的含义是在代码中不能对该变量进行修改。因此,它们本来就不是矛盾的。
说说内联函数和函数的区别?
内联函数和函数的区别:1.内联函数比函数多了一个关键字inline,内联函数避免了函数调用的开销,普通函数有调用的开销普通函数在被调用的时候,需要寻址(函数入口地址);内联函数不需要寻址; - 内联函数有一定的限制,内联函数体要求代码简单,不能包含复杂的结构控制语句,如果内联函数函数体过于复杂,编译器将自动把内联函数当成普通函数来执行;普通函数没有这个要求。
2. 内联函数的作用: 因为函数调用时候需要创建时间、参数传入传递等操作,造成了时间和空间的额外开销。通过编译器预处理,在调用内联函数的地方将内联函数内的语句复制到调用函数的地方,也就是直接展开代码执行,从而提高了效率,减少了一些不必要的开销。同时内联函数还能解决宏定义的问题。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通