C++面试八股(一)

news2024/11/23 9:30:52

目录

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.coloradmin.cn/o/1054586.html

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

相关文章

评估指标Pre\Rec\F1\AUC

AUC的计算方法同时考虑了分类器对于正例和负例的分类能力&#xff0c;在样本不平衡的情况下&#xff0c;依然能够对分类器作出合理的评价。AUC代表模型预估样本之间的排序关系&#xff0c;即正负样本之间预测的gap越大&#xff0c;auc越大. 来自 https://blog.csdn.net/pearl8…

wustctf2020_name_your_cat

wustctf2020_name_your_cat Arch: i386-32-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x8048000)32位&#xff0c;开了NX和canary int shell() {return system("/bin/sh"); }有个后门函数 unsigned int…

AutoHotkey ---- 统一所有软件的快捷键(分析篇)

文章目录 引言理论编程方案 引言 快捷键大家都不陌生.但是目前的快捷键普遍存在以下几个问题。 不统一,即word、ppt、浏览器、各种编辑器、邮件客户端等等&#xff0c;都有属于自己的一套快捷键。快捷键冲突&#xff0c;即不同软件使用了相同的快捷键&#xff0c;而且作用域是…

GNN PyG~torch_geometric 学习理解

目录 1. PyG Introduction 2. PyG Installation 2.1 PyG 安装常见错误及原因 2.2 PyG 具体安装步骤 3. torch_geometric packages torch_geometric.data.Data Dataset 与 DataLoader Dropout、BatchNorm 3. torch_geometric: 理解edge_index 3.1 理解 mini-batch edg…

[H5动画制作系列]帧代码运行顺序测试

刚开始接触Animate CC(过去叫:Flash),对于帧代码的执行顺序十分迷惑。所以,专门做一个简单代码顺序测试. 准备工作: 代码图层actions,第1帧和第10帧为关键帧。 背景图层bg,就一个字符串红色Test.界面如下: 代码测试步骤: 第1帧参考代码如下: 第10帧参考代码如下: …

​68条萝卜刀《乡村振兴战略下传统村落文化旅游设计》许少辉八一新书

​68条萝卜刀《乡村振兴战略下传统村落文化旅游设计》许少辉八一新书 ​68条萝卜刀《乡村振兴战略下传统村落文化旅游设计》许少辉八一新书

打包python模块代码到pypi

python中&#xff0c;我们会在自己业务中&#xff0c;重复性的使用某些功能。我们可以把这些公用的模块&#xff0c;打包上传&#xff0c;然后给需要的人使用&#xff0c;pypi给我们提供了这个机会 本期目录 一、准备工作 二、编写文件 三、上传下载 一、准备工作 1、需要git…

k8s实战案例之部署Nginx+Tomcat+NFS实现动静分离

1、基于镜像分层构建及自定义镜像运行Nginx及Java服务并基于NFS实现动静分离 1.1、业务镜像设计规划 根据业务的不同,我们可以导入官方基础镜像,在官方基础镜像的基础上自定义需要用的工具和环境,然后构建成自定义出自定义基础镜像,后续再基于自定义基础镜像,来构建不同服…

软件测试之Python基础学习

目录 一、Python基础 Python简介、环境搭建及包管理 Python简介 环境搭建 包管理 Python基本语法 缩进(Python有非常严格的要求) 一行多条语句 断行 注释 变量 基本数据类型(6种) 1. 数字Number 2. 字符串String 3. 列表List 4. 元组Tuple 序列相关操作方法 …

Unity 鼠标悬浮时文本滚动(Text Mesh Pro)

效果 直接将脚本挂载在Text Mesh Pro上&#xff0c;但是需要滚动的文本必须在Scroll View中&#xff0c;否侧会定位错误&#xff0c;还需要给Scroll View中看需求添加垂直或者水平布局的组件 代码 using System.Collections; using System.Collections.Generic; using UnityE…

【生物信息学】使用谱聚类(Spectral Clustering)算法进行聚类分析

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 3. IDE 三、实验内容 0. 导入必要的工具 1. 生成测试数据 2. 绘制初始数据分布图 3. 循环尝试不同的参数组合并计算聚类效果 4. 输出最佳参数组合 5. 绘制最佳聚类结果图 6. 代码整合 一、实验介绍…

【BLIP/BLIP2/InstructBLIP】一篇文章快速了解BLIP系列(附代码讲解说明)

文章目录 BLIP系列1. BLIP1.1 动机1.2 整体架构1.3 损失函数1.4 Captioning and Filtering(CapFilt)1.4.1 Why&#xff1f;1.4.2 方法 2. BLIP22.1 Q-Former的设计2.2 实现功能2.2.1 图像文本检索(Image-Text Retrieval)2.2.2 图像字幕(Image Captioning)2.2.3 视觉问答(VQA)2.…

1. Flink程序打Jar包

文章目录 步骤注意事项 步骤 用 maven 打 jar 包&#xff0c;需要在 pom.xml 文件中添加打包插件依赖 <build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-shade-plugin</artifactId><ver…

Python绘图系统24:绘图类型和坐标映射的关系

文章目录 类别与轴数坐标类别对映射的影像绘图类别对坐标轴的影响源代码 Python绘图系统&#xff1a; 前置源码&#xff1a; Python打造动态绘图系统&#x1f4c8;一 三维绘图系统 &#x1f4c8;二 多图绘制系统&#x1f4c8;三 坐 标 轴 定 制&#x1f4c8;四 定制绘图风格 &a…

CV面试知识点总结

一.卷积操作和图像处理中的中值滤波操作有什么区别&#xff1f; 1.1卷积操作 卷积操作是一种线性操作&#xff0c;通常用于特征的提取&#xff0c;通过卷积核的加权求和来得到新的像素值。1.2中值滤波 原文&#xff1a; https://blog.csdn.net/weixin_51571728/article/detai…

英飞凌Tricore原理及应用介绍06_系统定时器(STM)模块详解

目录 1.概述2 STM外设基本介绍3. STM模块使用原理3.1 64位数据如何同步读取?3.2 比较寄存器的原理?1.概述 STM全称为System Timer即系统定时器模块,在英飞凌Tricore芯片中,每个单独的CPU操作系统中配备一个系统定时器,为其操作系统程序调度提供时钟基础,在整个大系统中,…

【day9.30】消息队列实现进程间通信

write.c linuxlinux:~/23062/930$ cat write.c #include<myhead.h>#define ERR_MSG(msg) do{\fprintf(stderr, "__%d__:", __LINE__); \perror(msg);\ }while(0)typedef struct {long msgtype; //消息类型char data[1024]; //消息正文 }Msg_s;#define SIZ…

Java单链表

链表的介绍&#xff1a; 1) 链表是以节点的方式来储存的&#xff0c;是链式存储结构 2&#xff09;每个节点包含data域和next域&#xff0c;next域指向下一个节点 3&#xff09;链表内存储的元素不一定连续 4&#xff09;链表分带头节点的链表和不带头节点的链表 ​​​​ …

[论文笔记]UNILM

引言 今天带来论文Unified Language Model Pre-training for Natural Language Understanding and Generation的笔记,论文标题是 统一预训练语言模型用于自然语言理解和生成。 本篇工作提出了一个新的统一预训练语言模型(Unifield pre-trained Language Model,UniLM),可以同…

中间件漏洞靶场复现

一、简介 1.tomcat弱口令复现 通过弱口令复现的靶场复现&#xff0c;进一步熟悉了burpsuite的使用&#xff0c;冰蝎的使用以及爆破和木马生成waf上传的技术。 登陆到页面&#xff0c;先使用burpsuite对登陆进行拦截抓包&#xff0c;对参数进行修改破解爆破出密码。接着使用冰蝎…