【C/C++】C/C++面试八股

C/C++面试八股

  • C++和C语言的区别
  • 简单介绍一下三大特性
  • 多态的实现原理
  • 虚函数的构成原理
  • 虚函数的调用原理
  • 虚表指针在什么地方进行初始化的?
  • 构造函数为什么不能是虚函数
  • 虚函数和纯虚函数的区别
  • 抽象类
  • 类对象的对象模型
  • 内存对齐是什么?为什么要内存对齐
  • static关键字的作用
  • 指针和引用的区别
  • 介绍一下vector的扩容过程
  • vector如何释放内存空间
  • map与unordered_map的区别
  • 对于插入来说,operator[]与insert的区别
  • 对于访问来说,operator[]与.at的区别
  • new和malloc的区别
  • new的实现原理
  • operator new的原理
  • malloc的实现原理
  • 内存泄露的检测工具
  • 特殊类的设计
  • C++11的锁有哪些
  • C++11的智能指针
  • 几种排序的思路,代码实现

C++和C语言的区别

一.C++解决了很多C语言固有的缺陷:

  1. 针对C语言中存在命名冲突,C++提供了命名空间来解决
    2.C语言不支持函数缺省参数,C++也提供了缺省参数的方法
    3.在C语言中,由于宏函数的有效性无法检查,所以C++提出了内联函数解决

二.在C语言指针的基础上,C++提出了引用

三.C++可以实现函数重载,原因是C语言对于函数的区分是用函数名来区分的,而C++是使用函数名+函数参数列表来区分的,因此C语言中,只要函数名称一致,就会导致编译器报错,而C++中,可以设置函数名称一致,而参数列表不同的函数,作为函数的重载形式
四.C语言采用的是面向过程的编程思想,专注于过程。而C++采用的是面向对象的编程思想,关注的是对象,靠对象之间的交互完成
五.C语言的结构体中只能定义变量,而C++的类中,既可以定义变量也可以定义函数

简单介绍一下三大特性

封装:就是将数据和对数据的操作方式结合起来,隐藏细节,对外暴露一些接口,以供对象之间进行交互,本质上是为了让用户更好的管理类

继承:是一种代码的复用手段,目的是在原有类的基础上进行扩展,增加新的功能,生成新的类

多态:就是多种形态,当完成某个动作时,不同的对象去完成,产生不同的状态
多态可以分为静态多态和动态多态
静态多态是在程序编译阶段就确定了函数的执行动作,典型例子是:函数重载。
动态多态是在程序运行时通过传递的对象实际类型来确定函数的执行,典型例子是:函数的重写

多态的实现原理

多态的实现条件
1.需要首先让派生类重写基类的虚函数
2.通过基类的指针或引用来调用虚函数

多态的实现原理:
某个类成员函数被virtual修饰之后,该类的对象模型中就会有一个虚表指针,这个指针指向一个虚表,该虚表中就会存放虚函数地址。
当某个派生类将该基类继承之后,该派生类的对象模型中也会有一个和基类中一直的虚表指针,如果这个派生类将基类中的虚函数进行了重写,那么自己的虚表中就会将原来基类虚表中对应的虚函数指针替换
此时如果我们使用基类的指针或引用去调用虚函数,那么如果传递的是基类对象,那么就会通过this指针去调用基类对象的成员函数,如果传递的是子类对象,那么就会通过this指针去调用子类对象的成员函数。

虚函数的构成原理

在编译阶段,将虚函数按照在类中的声明次序依次添加到虚表中

在单继承体系下,子类虚表的构建原理:
1、原封不动将基类虚表中的内容拷贝一份到子类虚表中
2、如果子类中哪个函数重写了基类虚表中的虚函数,则将虚表中对应的虚函数指针替换为当前重写后的虚函数指针
3、将子类新增的虚函数按照在子类中声明的次序进行添加

虚函数的调用原理

通过实际传入的对象的this指针,拿到对应的虚表指针,再通过对应的虚表指针,找到对应的虚表,然后通过虚表中存放的虚函数地址,来进行虚函数的调用。

包含有虚函数的类对象,编译器在编译时,就为该对象创建了一个虚表指针,以便于能够正确的获取该类的虚表

虚表指针在什么地方进行初始化的?

在构造函数中,进行虚表的创建和虚表指针的初始化

构造函数为什么不能是虚函数

因为虚函数对应一个虚表指针,这个虚表指针是存储在对象的内存空间的,构造函数就是用来去开辟对象的内存空间 的,如果构造函数是虚函数,意味着在对象内存空间还不存在的就要去初始化对象内存空间中的值,是无法实现的

虚函数和纯虚函数的区别

虚函数目的是建立抽象模型,方便系统扩展
纯虚函数是不具体实现的函数,一种特殊的函数

虚函数必须是类的非静态成员

纯虚函数是虚函数的子集,用于抽象类,包含有纯虚函数的类是抽象类,不能实例化对象
因为有时候基类实例化对象是不合理的,例如:基类是动物,子类是猫狗,那么基类本身可以创建对象就是不合理的,那么用纯虚函数修饰之后,让基类无法创建对象才是较为合理的

抽象类

包含纯虚函数的类就是抽象类
抽象类不能实例化对象,只能在该类被派生之后,并且所有的纯虚函数都被重写之后,才能被创建对象

类对象的对象模型

类对象中只存储了类的成员变量,并且按照成员变量的声明顺序进行存储,遵循内存对齐原则,如果存在虚函数,那么会有虚表指针,如果存在虚拟继承,那么还会有一个虚基表指针。
在继承体系下,如果是普通的继承,那么子类对象的对象模型是:
首先是基类继承,然后是子类新增
在这里插入图片描述

如果是虚拟继承:
继承自多个基类,那么按照派生类的声明顺序进行。
每个来自基类的对象模型中,只存储一个虚基表指针,指向各自基类对应位置
然后是子类新增,最后是基类成员变量
在这里插入图片描述

内存对齐是什么?为什么要内存对齐

1、提高内存访问效率
2、减小内存占用量

static关键字的作用

static关键字的作用: static关键字的作用

指针和引用的区别

1.指针存储的是地址,而引用是对变量的一个别名
2.引用在定义时必须初始化,而指针不用
3.指针可以通过修改值来改变指针的指向,引用关系一旦确立,引用的实体就不能改变了
4.sizeof时,传递的是指针,计算的是指针占空间的大小,引用是变量类型的大小
5.指针需要显式解引用,引用不用
6.存在空置指针,而不存在空值引用

介绍一下vector的扩容过程

vector如何释放内存空间

map与unordered_map的区别

1.map的底层是红黑树,unordered_map底层是哈希表
2.map是按照key有序的,unordered_map无序
3.map的查询效率是O(logn),unordered_map是O(1)
4.map更适合需要数据有序,对查询效率不是那么高的场景,unordered_map适合对查询效率极高的场景

对于插入来说,operator[]与insert的区别

如果key存在,那么都会插入失败,但是operator[]会将原来的key对应的value替换为新的value,而insert不进行任何操作
如果key不存在,那么都会插入成功,通过key和value构造键值对,进行插入

operator[]底层调用的是insert,insert返回的是对应位置的迭代器,operator[]拿到返回的迭代器,返回的是key对应的value

对于访问来说,operator[]与.at的区别

如果key存在,operator[]和.at()一样会返回key对应的value
如果key不存在,operator[]会key和默认的value构成键值对,插入map中

new和malloc的区别

1.new是关键字,malloc是库函数
2.new申请空间失败会抛异常,malloc不会
3.new只需要传递类型,编译器会根据类型判断申请空间大小,malloc需要手动传递字节数
4.new申请空间之后不需要进行类型转换,malloc需要
5.new在申请空间之后还会调用构造函数进行对象的构造,而malloc不会,同理delete会自动调用析构函数,而free不会

new的实现原理

1、调用operator new()函数申请空间
2、在申请的空间上执行构造函数,完成对象的构造

operator new的原理

1、调用malloc函数申请空间
2、如果申请成功,返回空间地址,如果申请失败,会执行用户定义的方法,继续申请空间,如果用户没有定义申请失败的方法,那么就会抛异常

malloc的实现原理

1、内存管理:内存管理的数据结构是一个链表, 每个节点表示的是一个内存块,调用malloc时,先遍历该链表找到一块足够大的内存块,标记为已分配状态
2、内存分配,将已分配的内存块首地址返回给程序

内存泄露的检测工具

在linux下进行内存泄漏的检测工具:valgrind
在win下的内存泄漏检测工具:VLD

特殊类的设计

设计类不能被继承:将构造函数私有化
设计类不能被拷贝:将拷贝构造和赋值运算符重载只声明不定义
设计类只能从堆上创建对象:
方法一:将构造函数和拷贝构造函数私有化,设置一个静态成员函数,函数内通过new创建对象,返回对象指针
设计类只能从栈上创建对象:
方法一:将构造函数私有化,将operator new()禁掉
方法二:将构造函数和拷贝构造函数私有化,设置一个静态成员函数,在该函数中调用构造函数,返回对象

设计一个单例类:
饿汉模式:将构造拷贝构造赋值运算符都私有化,类内声明一个私有的静态类对象和一个公有的静态成员函数,在函数内对静态类对象进行初始化,返回对象指针

懒汉模式:将构造函数和拷贝构造函数和赋值运算符重载都私有化,类内声明一个私有的静态类对象指针和一个公有的静态成员函数,在函数中new一个对象的指针赋值给该静态对象指针。需要注意的是double chack

C++11的锁有哪些

六大种:
1、mutex
2、recursive_mutex
3、timed_mutex
4、recursive_timed_mutex
5、lock_guard:对mutex进行封装,实现了RAII,可以预防死锁
6、unique_lock:在lock_guard上增加了加锁解锁查看锁状态等功能

C++11的智能指针

auto_ptr:已资源管理权限转移的方式解决浅拷贝,弃用,容易造成野指针

unique_ptr:已资源独占的方式解决浅拷贝,无法拷贝,不方便

shared_ptr:已资源计数的方式解决浅拷贝,容易造成循环引用的问题,解决方式是weak_ptr,用ListNode的例子解释

几种排序的思路,代码实现

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2023年上海市安全员B证证模拟考试题库及上海市安全员B证理论考试试题

题库来源:安全生产模拟考试一点通公众号小程序 2023年上海市安全员B证证模拟考试题库及上海市安全员B证理论考试试题是由安全生产模拟考试一点通提供,上海市安全员B证证模拟考试题库是根据上海市安全员B证最新版教材,上海市安全员B证大纲整理…

金融生产存储亚健康治理:升级亚健康 3.0 ,应对万盘规模的挑战

随着集群规模的不断扩大,硬盘数量指数级上升,信创 CPU 和操作系统、硬盘多年老化、物理搬迁等多种复杂因素叠加,为企业的存储亚健康管理增加了新的挑战。 在亚健康 2.0 的基础上,星辰天合在 XSKY SDS V6.2 实现了亚健康 3.0&#…

git之merge和rebase的区别

准备 创建仓库 test-01文件 test-02文件 创建test01分支和test02分支 这里我们使用idea打开源代码 test02分支同操作 大致操作 test01分支对文件test01文件操作: 1.添加内容:test01第一次修改1 2.git commit 3.添加内容: test01第二次…

基于监督学习的多模态MRI脑肿瘤分割,使用来自超体素的纹理特征(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

picoctf_2018_got_shell

picoctf_2018_got_shell Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)32位,只开了NX int __cdecl __noreturn main(int argc, const char **argv, const char **envp) {_DWOR…

蓝桥杯打卡Day15天

文章目录 买不到的数目错误票据 一、买不到的数目OJ链接 本题思路:引理:给定a,b,若dgcd(a,b)>1 ,则一定不能凑出最大数。结论:如果 a,b均是正整数且互质,那么由 axby,x≥0,y≥0 不能凑出的最大数是 ab−a−b。 证…

什么是Spring Bean?作用域有哪些

Spring Bean详解:作用域与示例 Spring框架是一个强大的Java开发框架,它提供了大量的功能和组件来简化企业级应用程序的开发。其中,Spring Bean是Spring框架中的一个核心概念,它扮演着重要的角色,用于管理和组织应用程…

FreeRTOS(以STM32F1系列为例子)

目录 任务管理任务函数任务控制块顶层任务状态创建任务xTaskCreatexTaskCreateStaticxTaskCreateRestricted 任务优先级和心跳设置心跳设置优先级概述vTaskPrioritySetuxTaskPriorityGet 非运行态扩充阻塞态vTaskDelay挂起状态vTaskSuspend就绪状态完整的状态转换图延迟函数vTa…

redis-设置从节点

节点结构 节点配置文件 主节点 不变 6380节点 port 6380 slaveof 127.0.0.1 63796381节点 port 6381 slaveof 127.0.0.1 6380启动 指定配置文件的方式启动 D:\jiqun\redis\Redis-6380>redis-server.exe redis.windows.conf启动时,会触发同步数据命令 主节点…

在Qt中,怎么获取到在mainwindow.ui文件中添加的控件

2023年9月30日,周六晚上 假设我在mainwindow.ui中添加了一个名为textEdit的QTextEdit对象 在mainwindow.cpp中,可以通过ui对象来获取到这个控件

Spring MVC 中的国际化和本地化

Spring MVC 中的国际化和本地化 国际化(Internationalization,简称i18n)和本地化(Localization,简称l10n)是构建多语言应用程序的重要概念。Spring MVC提供了丰富的支持,使开发人员能够轻松地处…

(三) gitblit管理员手册

(一)gitblit安装教程 (二) gitblit用户使用教程 (三) gitblit管理员手册 目录 权限管理创建仓库时创建用户普通用户 管理员用户访问限制和访问权限仓库创建权限分配 Teams普通组管理员组 参考资料 权限管理 创建仓库时 选择指定的人员查看,克隆,推送 不允许fork 对应Anonymo…

idea Springboot 高校科研资源共享系统VS开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 springboot 高校科研资源共享系统是一套完善的信息系统,结合springboot框架和bootstrap完成本系统,对理解JSP java编程开发语言有帮助系统采用springboot框架(MVC模式开发), 系统具有完整的源代码和数据…

Lua学习笔记:require非.lua拓展名的文件

前言 本篇在讲什么 Lua的require相关的内容 本篇需要什么 对Lua语法有简单认知 对C语法有简单认知 依赖Visual Studio工具 本篇的特色 具有全流程的图文教学 重实践,轻理论,快速上手 提供全流程的源码内容 ★提高阅读体验★ 👉 ♠…

基于vue+Element Table Popover 弹出框内置表格的封装

文章目录 项目场景:实现效果认识组件代码效果分析 封装:代码封装思路页面中使用 项目场景: 在选择数据的时候需要在已选择的数据中对比选择,具体就是点击一个按钮,弹出一个小的弹出框,但不像对话框那样还需…

【RocketMQ】基本使用:Java操作RocketMQ(rocketmq-client)

【RocketMQ】基本使用&#xff1a;Java操作RocketMQ&#xff08;rocketmq-client&#xff09; 1.引入依赖 <dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-client</artifactId><version>4.3.2</version>…

C++ AB组辅导课

C AB组辅导课 蓝桥杯C AB组辅导课 第一讲 递归与递推 Acwing1、整数划分(递归)2、acwing92. 递归实现指数型枚举10凑算式(全排列)11李白打酒(全排列)12、棋牌总数(递归)13、剪邮票(递归)14、1050. 鸣人的影分身 (递归或动态规划(记忆化搜索))15、方格分割 &#xff08;dfs思维&…

【软件评测】Apowersoft 傲软抠图AI智能换背景工具软件

现如今的数字图像处理已经成为人们生活中不可或缺的一部分&#xff0c;而图像抠图作为其中的重要环节&#xff0c;更是被广泛应用于设计、摄影、广告等领域。为了满足用户的需求&#xff0c;Apowersoft推出了一款傲软抠图AI智能换背景工具&#xff0c;宣称能够自动抠图并智能替…

应用架构的演进:亚马逊的微服务实践

当你在亚马逊上购物时,或许不会想到,你看到的这个购物网站,其背后技术架构经历了什么样的变迁与升级。 还记得上世纪 90 年代,那个只卖书的网上书店吗?那时的亚马逊,不过是一个架构简单的网站,所有的功能都堆积在一个庞大的软件堡垒里。随着更多业务的增加、更新和迭代,这个软…

【数据结构篇】堆

文章目录 堆前言基本介绍认识堆堆的特点堆的分类堆的操作堆的常见应用 堆的实现JDK 自带的堆手动实现堆 堆 前言 本文主要是对堆的一个简单介绍&#xff0c;如果你是刚学数据结构的话&#xff0c;十分推荐看这篇文章&#xff0c;通过本文你将对堆这个数据结构有一个大致的了解…