C++面试八股(一)

目录

C和C++的区别

1、语言特性

2、内存管理

3、C++的库更加丰富

4、对异常的处理

什么是封装继承多态?

 封装

 继承

多态

new和malloc的区别

 STL容器有哪些?容器对应的使用场景?(挑一个你认为最熟悉的容器)

vector、list

应用场景

迭代器失效问题

stack、queue、priority_queue

map、set

 map和set的区别?

map作为一个迭代有序的容器,当键值key是一个自定义类时,如何保证它是有序的?

map已经有了一个键值key,如果重复的插入这个键值key但是设置不同的value,是插入失败还是覆盖原来的value?

unordered_map、unordered_set

什么是哈希冲突?如何解决哈希冲突?


C和C++的区别

        C语言是一门面向过程的语言,而C++是一门面向对象的语言。这就完了?那么这就完了!!

1、语言特性

        从语言特性上来讲C++完全继承了C语言。C语言是一门面向过程的语言,更加注重执行的过程,C++在继承了C语言语法的同时引入了类,封装,继承,多态。使得C++在使用上变得更加灵活和可扩展,是一门强大的面向对象语言。

        问题延展:什么是封装继承和多态?如何实现多态?C++有几种继承方式?多继承会有哪些问题?如何解决?虚继承原理是什么?…

2、内存管理

        在内存管理方面,C++有更加丰富的内存管理机制,可以通过析构函数和运算符重载自动释放来管理动态内存,C语言则需要手动的释放。同时在内存的申请和访问上也有不同,C++倾向于使用new关键字申请动态内存,C语言则使用malloc等函数来申请动态内存。

        问题延展:new和malloc的区别?动态内存在哪里申请?什么是内存碎片?C和C++中的内存泄漏是什么?如何避免内存泄漏?什么是RAII技术?…

3、C++的库更加丰富

        C++标准库引入了标准模板库STL,STL将很多可复用的数据结构和算法,整合成为容器提供给开发人员使用,以便开发人员能更高效轻松的编写高质量代码。而C语言在这方面支持相对较少,更多的使用使用第三方库。

        问题延展:举例STL容器,你对哪个容器最熟悉?它的应用场景是什么?什么是深浅拷贝?默认构造什么时候生成?…

4、对异常的处理

        在错误的处理中,C++还使用了抛异常的机制,允许开发人员通在程序执行的过程中遇到错误时引发异常,并在适当的地方捕获异常和处理,C语言通常使用返回错误值表示函数在执行时出现错误的错误信息,对比一下,C++的异常处理机制可以提供更好的安全性,可以利用异常处理机制保证资源的正确释放和状态的一致性。

        问题延展:如何处理异常?什么是异常的捕获顺序?C++中可以抛出哪些类型的异常?…

什么是封装继承多态?

对于我们新手程序员,这个基本是必问的了,逃不掉的。没啥好说的就学吧,学不完的……

 封装

        封装就是将成员和函数用类包裹起来,提供C++提供的访问限定符,来限定哪些是可以被外部使用的函数和成员,哪些是不能被直接访问的函数和成员。规范了使用者对类使用的方式,只通过调用函数提供的接口对类进行操作,同时提高了成员访问的安全性。

        问题延展:访问限定符有哪些?说一下static关键字、如何访问静态的成员和成员函数?静态函数如何使用类内的成员?什么是构造函数?构造函数什么时候生成?…

class A{
public:void func1(){ std::cout << "public" << std::endl; } // 外部可以访问
protected:void func2() { std::cout << "protected" << std::endl; } // 继承的子类可以访问
private:        void func3() {std::cout << "private" << std::endl; }   // 只有自己可以访问
}

 继承

        继承是指一个类可以从另一个类继承属性,继承的一方我们称为子类,被继承的一方我们称为父类,子类通过继承父类的属性可以实现代码的重用,同时子类也可以通过覆盖的方式修改其行为,最重要的是继承可以实现多态。

class A{
protected:void func(){ std::cout << "i'm A::func() << std::endl; "}
}class B : public A{void print(){A::func();}
}

        问题延展:C++有几种继承方式?什么是多继承?、菱形继承是什么?有什么问题?如何解决?…

多态

        多态就是同一个函数可以实现不同的效果,分为静态多态和动态多态。

       静态多态也叫做重载,他是在相同作用域下通过函数参数不同,或者参数位置不同实现的两个函数名相同,但可以通过传入不同参数实现不同的函数效果。其本质是通过对汇编代码的函数名用参数修饰,而我们在表面上看两个函数名相同的函数,在链接上是通过查找不同的函数名链接,实现重载。

// 重载
int max(int a,int b) { return a > b : a : b }; int max(double a,double b) { return a > b : a : b; }

        动态多态是通过子类继承父类,并对父类的虚函数重写来实现的,然后通过父类的指针或引用,来实现多态调用。实现无论是哪个对象传递给给父类指针(引用)都可以实现对自己重写父类虚函数的调用,是两个不同作用域下实现的,并且重写函数的参数和函数名返回值都必须与父类的要重写的虚函数一致。

​class A{
protected:virtual void func() { std::cout << "i'm A::func() << std::endl; "}
}class B : public A{virtual vodi func() { std::cout << "i'm B::func()" << std::endl; }
}// 多态调用
void f(A* p)
{p->func();
}int main()
{A a;B b;f(&a);f(&b);return 0;
}
​

        问题延展:虚函数如何实现多态?什么是静态绑定和动态绑定?虚表什么时候生成?父类的对象可以实现多态吗?为什么?析构函数可以声明为虚函数,为什么构造函数不行?…

new和malloc的区别

        你以为这就是一个简单的问题吗?那你就错了,这个问题可坑了。只是作为引出,面试官后续的问题,一定会把你往内存的问题上带。

1、new是C++上的一个操作符,作为操作符new可以使用运算符对new进行运算符重载,malloc则是C语言的一个用来申请动态内存的函数,new和malloc都是在虚拟内存的堆(heap)分配空间,堆区的空间由程序员自己管理和手动释放,new对应的释放为delete,malloc释放空间使用free函数。 (关键词:操作符和函数,堆区释放空间)

2、new会自动计算需要分配的内存大小并且new在分配空间时会调用对象的够着函数来构造对象,malloc开辟空间需要手动计算,并且malloc就只负责向堆区申请空间不会调用构造函数(关键词:自动分配和手动计算,调用和不调用)

3、new申请完成会返回一个申请的对象指针,malloc申请完成会返回一个void*的指针,并且需要我们对这个指针进行强转。new在申请失败后会抛出异常,而malloc失败则会返回一个空指针。(关键词:返回值,抛异常,空指针)

加分项:在申请空间时开始只能获取到虚拟内存的空间,只有在初始化我们分配的空间后,虚拟内存才会通过页表和缺页中断方式才能与物理内存建立映射关系。所以new操作符在分配内存空间后会调用构造函数来初始化对象,并与物理内存建立映射关系。而malloc因为不会对对象进行初始化,刚开始并不会与内存建立映射关系,需要对空间初始化后,才能建立映射关系。

【其实到这里就可以看出面试官问出这个问题,无非就是想考察面试者对内存的理解和掌握】

        问题延展:什么是虚拟内存?虚拟内存地址空间发布?堆区和栈区的区别?什么是内存碎片?什么是内存对齐?什么是内存泄漏?如何避免(必扯到RAII,智能指针)?缺页中断……

 STL容器有哪些?容器对应的使用场景?(挑一个你认为最熟悉的容器)

刚开始可以把STL常见的容器都讲一遍,什么vector,list啦...巴拉巴拉的一大堆想起来的全部讲一遍。然后要熟悉容器的对应场景和容器的特征。最后再一一介绍。

vector、list

        vector和list都是线性表,vector本质是一个动态开辟的数组,它的每个元素在地址上都是连续的,list则对应数据结构的带头双向循环链表,通过前驱指针和后继指针指针来连接每一个元素节点。

应用场景

        vector得益于地址的连续,适合做查找,排序操作,同时支持通过下标访问元素,在尾插尾删的时间复杂度为O(1)。

        list依靠指针连接节点,所以在添加和删除节点上,list可以动态的调整自己的长度。并且由于list作为链表在链表的任意节点插入元素都是O(1)的时间复杂度,适合需要频繁进行插入和删除数据的场景。

迭代器失效问题

        当遍历vector容器时,对vector中的元素进行了插入或删除操作,导致迭代器无法正确的访问到vector中的元素,也就是迭代器指向了一个错误的地方。

#include <vector>int main()
{std::vector<int> nums = {1,2,3,4,6};for(auto it = nums.begin();it != nums.end();++it){if(*it == 4){//  nums.insert(it,5);// 迭代器失效it = nums.insert(it,5); // 让迭代器指向新的位置}}return 0;
}

        list使用了指针连接方式,所以当在遍历list时,插入或删除list中元素节点,迭代器会指向新插入的节点或者是删除节点的后一个节点,不会导致迭代器失效。

        问题延展:什么是深浅 拷贝?push_back和empty_back区别?左值引用右值引用?(暂时没想出来还有什么问题,可以提醒一下,接下来可能会直接转排序问题)……

stack、queue、priority_queue

        stack栈,是一个后进先出的数据结构,不是在虚拟内存地址空间上的那个栈,它适用于一些需要后进先出的场景,例如括号匹配、逆波兰表达式、循环模拟树的前中后序(深度优先)等

        queue队列,是一个先进先出的数据结构,同样的适用于一些需要先进先出的场景,例如层序遍历(广度优先)、线程池任务队列、生产者消费者模型等。

        priority_queue,使用的是数据结构中的堆(heap),同样也区别于虚拟内存地址空间上的堆,在思想上是使用数组模拟一个二叉树,通过插入元素向下调整,删除元素向上调整。保证堆顶的数据始终为整个堆中最大或者最小的,保持堆顶为最大数据的叫做大堆,最小数据的为小堆。向上调整和向下调整的策略可以用来做堆排序,还可以解决topk问题,以及一些需要考虑优先级的场景。

       问题延展:堆排序的时间复杂度?构建堆的时间复杂度?(暂时没想到)……

map、set

 map和set的区别?

        map和set的底层都同样使用了红黑树结构,map和set是封装了红黑树。

1、map使用的是键值对的方式存储数据,set只存储唯一元素没有键值对的概念。(关键词:键值对)

2、map内部重载了方括号([]),可以使用方括号通过键值查找或添加元素。set只能使用insert插入元素。(关键词:重载运算符)

3、红黑树的前序是有序的,所以遍历map和set也都是有序的。但区别在于map按照键值来排列顺序,set使用存储的元素值排序。同时map的key存储只能是唯一的,set的存储的每一个元素也是唯一的(关键词:key值排序,元素值排序)

map作为一个迭代有序的容器,当键值key是一个自定义类时,如何保证它是有序的?

        可以通过使用仿函数的方式,仿函数重载括号来实现元素的比较方式,例如string可以使用首元素字典序的方式来排序。除了仿函数,还可以使用lambda表达式来自定义比较方法。(关键词:仿函数,重载括号,lambda)

map已经有了一个键值key,如果重复的插入这个键值key但是设置不同的value,是插入失败还是覆盖原来的value?

        如果map中已经有了一个key值,那么重新插入一个key值相同的元素会覆盖掉原有的value。也就是map对于重复的键值会覆盖原来的值,不会导致插入失败。(关键词:覆盖)

       问题延展:什么是红黑树?红黑树的时间复杂度是多少?为什么选择红黑树而不是其他数据结构?如何插入和删除节点以保持红黑树的平衡?……

unordered_map、unordered_set

        unordered_map和unordered_set的底层使用的数据结构是哈希表(散列表)。哈希表是一个插入和查找操作都是O(1)时间复杂度,而哈希表的底层是一个数组,插入元素是对元素重新计算,然后映射到特定的数组下标来存储。但与map、set不同的是unordered_map和unordered_set存储的数据是无序的。

什么是哈希冲突?如何解决哈希冲突?

        哈希冲突是当对插入元素进行映射时时,映射到的相应数组下标已经存在其他元素,这就是哈希冲突。

解决方法:

        1、线性探测

                线性探测其实就是,当发生哈希冲突时,向映射位置的下一个位置查看是否为空,如果下一个地址没有存储元素,直接存储到该位置,否则继续找空位置。

        2、二次探测

        二次探测通过计算一个增量序列来寻找下一个可用的位置,具体来说就是,当发生哈希冲突时,二次探测会计算一系列的增量值,通常使用二次方程来计算增量。假设哈希函数计算得到的哈希值为h,那么二次探测会依次检查位置h+1,h+4,h+9,h+16,以此类推,直到找到一个空闲位置或遍历完整个哈希表。

        3、链地址法

        这个很好理解,就是哈希表的每个地址不再只能存储一个元素了,我的每个地址存储的是一个链表,当你发生冲突时,直接将这个元素尾插到链表最后一个节点位置,从而解决哈希冲突。当然,存储的不一定就是链表,也可以存储红黑树来加快查找效率,这也是库里使用的解决方法。

        

       问题延展:哈希表的扩容和缩容是如何实现的?哈希表的负载因子是什么?如何影响哈希表的性能?应用场景…

就先写到这了,这篇文章其实也算是我自己的复习总结吧,但希望这篇文章对看到的人能有所帮助吧,最后,今天是2023年10月1日,也祝大家节日快乐,祖国万岁!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/150103.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

前端相关题目随笔

Vh虽然获取到了视口高度&#xff0c;但是vh会随着屏幕的、大小变化&#xff0c;所以当减去一个数字之后&#xff0c;就会显示错误。 生成id 如果没有设置id&#xff0c;则可以通过new Date.getTime()获取一个时间&#xff0c;作为一个单独的id&#xff0c;也可以通过下载uuid生…

Cocos Creator3.8 项目实战(六)Combobox控件的实现和使用

在cocoscreator 中&#xff0c;没有Combobox控件&#xff0c;无奈之下只能自己动手写一个。 ⚠️ 文末附 ComboBox.ts 、ComboBoxItem.ts 完整源码&#xff0c; 可直接拿去使用。 实现原理&#xff1a; 1、Combobox 背景图background 是一个sprite 控件&#xff0c;上面放了一…

【二】spring boot-设计思想

spring boot-设计思想 简介&#xff1a;现在越来越多的人开始分析spring boot源码&#xff0c;拿到项目之后就有点无从下手了&#xff0c;这里介绍一下springboot源码的项目结构 一、项目结构 从上图可以看到&#xff0c;源码分为两个模块&#xff1a; spring-boot-project&a…

Python 无废话-办公自动化Excel修改数据

如何修改Excel 符合条件的数据&#xff1f;用Python 几行代码搞定。 需求&#xff1a;将销售明细表的产品名称为PG手机、HW手机、HW电脑的零售价格分别修改为4500、5500、7500&#xff0c;并保存Excel文件。如下图 Python 修改Excel 数据&#xff0c;常见步骤&#xff1a; 1&…

Go Gin Gorm Casbin权限管理实现 - 2. 使用Gorm存储Casbin权限配置以及`增删改查`

文章目录 0. 背景1. 准备工作2. 权限配置以及增删改查2.1 策略和组使用规范2.2 用户以及组关系的增删改查2.2.1 获取所有用户以及关联的角色2.2.2 角色组中添加用户2.2.3 角色组中删除用户 2.3 角色组权限的增删改查2.3.1 获取所有角色组权限2.3.2 创建角色组权限2.3.3 修改角色…

麻雀搜索算法(SSA)(含MATLAB代码)

先做一个声明&#xff1a;文章是由我的个人公众号中的推送直接复制粘贴而来&#xff0c;因此对智能优化算法感兴趣的朋友&#xff0c;可关注我的个人公众号&#xff1a;启发式算法讨论。我会不定期在公众号里分享不同的智能优化算法&#xff0c;经典的&#xff0c;或者是近几年…

Sql server 使用DBCC Shrinkfile 收缩日志文件

磁盘空间有限&#xff0c;需要收缩日志文件释放空间。 数据库名称上右击属性->文件,逻辑名称日志文件默认名称为“_log”结尾。 alter database 数据库 set recovery simple dbcc shrinkfile(XXX_log,2,truncateonly) alter database 数据库 set recovery full

QT聊天室阶段性记录(完善中:注册功能,数据库存储)

server.h #ifndef SERVERDEMO_H #define SERVERDEMO_H#include <QObject> #include <QTcpServer> #include <QMap> #include <QSqlDatabase> //数据库管理类 #include <QSqlQuery> //执行sql语句的类 #include <QSqlRecord> //数据库…

Netty

目录 引言&#xff1a; 什么是Netty&#xff1f; Netty和Tomcat有什么区别&#xff1f; 为什么Netty受欢迎&#xff1f; Netty为什么并发高 Netty为什么传输快 为什么说Netty封装好&#xff1f; 使用示例&#xff1a; 步骤1: 添加Netty依赖 步骤2: 创建服务器启动类 步…

【JavaEE】_构造HTTP请求与HTTPS

目录 1. 构造HTTP请求 1.1 form标签构造HTTP请求 1.1.1 form标签构造GET请求 1.1.2 form标签构造POST请求 1.2 通过ajax构造HTTP请求 1.3 form与ajax 1.4 使用ajax构造HTTP请求 2.HTTPS 2.1 对称加密 2.2 非对称加密 2.3 证书 1. 构造HTTP请求 1.1 form标签构造HTT…

idea插件(free mybatis plugin)

安装&#xff1a; 由于我用的idea版本是2023的&#xff0c;所以搜出来的是Free MyBatis Tool,和Free MyBatis plugin是一样的 主要功能&#xff1a; 生成mapper xml文件 快速从代码跳转到mapper及从mapper返回代码 mybatis自动补全及语法错误提示 集成mybatis generator gui…

Spring Boot中的@Controller使用教程

一 Controller使用方法&#xff0c;如下所示&#xff1a; Controller是SpringBoot里最基本的组件&#xff0c;他的作用是把用户提交来的请求通过对URL的匹配&#xff0c;分配个不同的接收器&#xff0c;再进行处理&#xff0c;然后向用户返回结果。下面通过本文给大家介绍Spr…

JavaScript系列从入门到精通系列第十七篇:JavaScript中的全局作用域

文章目录 前言 1&#xff1a;什么叫作用域 一&#xff1a;全局作用域 1&#xff1a;全局变量的声明 2&#xff1a;变量声明和使用的顺序 3&#xff1a;方法声明和使用的顺序 前言 1&#xff1a;什么叫作用域 可以起作用的范围 function fun(){var a 1; } fun();consol…

Linux YUM源(本地/网络源)配置详解

目录 一、挂载 二、实现思路 三、建立本地源 配置详解&#xff1a; 四、建立网络源 配置详解&#xff1a; 五、验证 一、挂载 ——将光盘挂载到 /mnt ——挂载光盘时要保证虚拟机光盘处于连接状态 命令&#xff1a;[rootlocalhost mnt]# mount /dev/sr0 /mnt # 此时还…

MongoDB数据库网站网页实例-编程语言Python+Django

程序示例精选 PythonDjangoMongoDB数据库网站网页实例 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对《PythonDjangoMongoDB数据库网站网页实例》编写代码&#xff0c;代码整洁&#xff0c;…

海信电视U8发布,一场针对画质的“定向跨越”

作者 | 曾响铃 文 | 响铃说 最近在重温《西游记》时&#xff0c;我才发现“灵性”这个东西有多讨喜。 在灵台方寸山&#xff0c;孙悟空头上被铛铛铛敲了三下&#xff0c;就悟出了师傅要为其深夜传授妙法&#xff0c;而这样的“感知”和“觉悟”&#xff0c;却在进修了那么多…

次方计数的拆贡献法(考虑组合意义)+限定类问题善用值域与位置进行ds:1006T3

对于多次方的计数问题可以考虑拆贡献。 题目问 ∣ S ∣ 3 |S|^3 ∣S∣3&#xff0c; ∣ S ∣ |S| ∣S∣ 表示选的点数。相当于在 ∣ S ∣ |S| ∣S∣ 中选了3次&#xff0c;也就是选了3个可相同的点。 先考虑3个不相同点的贡献&#xff0c;对应任意3个点&#xff0c;必然会对…

Flow Chart 的中文意思是什么?请说出自然界中河流的三种流动方式。事件驱动是什么?

目录 Flow Chart 的中文意思是什么? 请说出自然界中河流的三种流动方式。 事件驱动是什么? 请介绍一下 亚特兰大这座城市 Flow Chart 的中文意思是什么? 流程图 请说出自然界中河流的三种流动方式。 自然界中的河流可以以多种不同的方式流动&#xff0c;以下是其中三…

在Linux中软链接和硬链接的区别是什么?

2023年10月6日&#xff0c;周五晚上 目录 软链接(SymbolicLink):硬链接(HardLink):区别: 软链接(SymbolicLink): 软链接本身只是一个指向其他文件或目录的指针,不占用任何磁盘空间。软链接的修改或删除不会影响原文件。软链接可以指向不同文件系统中的文件。 硬链接(HardLink…

c++运算符重载实现

#include <iostream> #include <cstring> using namespace std; class myString { private:char *str;int size; public://无参构造myString():size(10){str new char[size]; //构造出一个长度为10的字符串strcpy(str,""); //赋值为空串}//有…