网络上收集的C++常见面试题
1. 进程与线程的关系,图解
进程简单理解就是我们平常使用的程序,进程拥有自己独立的内存空间地址,拥有一个以上的线程。
线程可以理解为轻量级的进程,是程序执行的最小单元。在某个进程启动后,会默认产生一个主线程,主线程可以创建多个子线程,因此线程是存在进程内的,位于一个进程内的线程可以共享部分资源,故线程间的切换比进程少得多。
多线程可以并行、并发执行(如互联网开发中高并发编程技术),可以共享数据和资源,线程间采用多种线程通信方式进行通信。
相关链接:https://baijiahao.baidu.com/s?id=1630348661230501723&wfr=spider&for=pc
2. 线程的基本概念、线程的基本状态及状态之间的关系
基本概念:线程,即轻量级进程(LWP:Light Weight Process),是程序执行流的最小单元。一个线程是进程的一个顺序执行流。同类的多个线程共享一块内存空间和一组系统资源,线程本身有一个供程序执行时的堆栈。线程在切换时负荷小,因此,线程也被称为轻负荷进程。一个进程中可以包含多个线程。
在一个进程内部,要同时干多件事情,就需要同时运行多个子任务,我们把进程内的这些子任务叫做线程。
多线程就是为了同步完成多项任务(在单个程序中同时运行多个线程完成不同的任务和工作),不是为了提高运行效率,而是为了提高资源使用效率来提高系统的效率。
基本状态:就绪、阻塞和运行三种基本状态。
就绪状态,指线程具备运行的所有条件,逻辑上可以运行,在等待处理机;
运行状态,指线程占有处理机正在运行;
阻塞状态,指线程在等待一个事件(如信号量),逻辑上不可执行。
状态之间的关系参考:线程的基本概念、线程的基本状态及状态之间的关系
3. https://blog.csdn.net/morewindows/article/details/7392749
4. 多态性可以简单地概括为“一个接口,多种方法”,程序在运行时才决定调用的函数,它是面向对象编程领域的核心概念。多态(polymorphisn),字面意思多种形状。
C++多态性是通过虚函数来实现的,虚函数允许子类重新定义成员函数,而子类重新定义父类的做法称为覆盖(override),或者称为重写。(这里我觉得要补充,重写的话可以有两种,直接重写成员函数和重写虚函数,只有重写了虚函数的才能算作是体现了C++多态性)而重载则是允许有多个同名的函数,而这些函数的参数列表不同,允许参数个数不同,参数类型不同,或者两者都不同。编译器会根据这些函数的不同列表,将同名的函数的名称做修饰,从而生成一些不同名称的预处理函数,来实现同名函数调用时的重载问题。但这并没有体现多态性。
那么多态的作用是什么呢,封装可以使得代码模块化,继承可以扩展已存在的代码,他们的目的都是为了代码重用。而多态的目的则是为了接口重用。也就是说,不论传递过来的究竟是那个类的对象,函数都能够通过同一个接口调用到适应各自对象的实现方法。
之前学的Direct2D以及Direct3D都是通过接口调用来实现多种方法。
实现多态有两个条件: 一是虚函数重写
二是对象调用虚函数时必须是指针或者引用
重写 :子类的函数覆盖父类的函数,子类重新定义父类的虚函数(针对虚函数而言)
常用于继承关系中
特点:
(1)父类和子类函数名相同
(2)父类和子类的参数以及返回值值相同
(3)父类的函数中必须含有virtual关键字。
重载:函数名相同,参数不同。与继承没有直接关联
特点:
(1)相同的作用域 (都在类中,或者类外)
(2)函数名相同
(3)参数不同
(4)virtual关键字可有可无
(5)返回值可以不同
隐藏:子类的函数屏蔽了父类的同名函数。只有是同名函数,没有virtual,不管参数列表是否形同。
父类的函数都会被隐藏。
(1)不在同一个作用域(分别位于子类和父类)
(2)函数名相同
(3)返回值可以不同
(4)参数可以不同,此时,不论有无 virtual 关键字,基类的函数将被隐藏
(与重载有区别)
(5)参数相同,但是基类函数没有 virtual关键字。此时,
基类的函数被隐藏(注意与重写的区别)
相关链接:从一个面试题来谈C++的多态性
5. TCP三次握手,四次挥手
三次握手:(SYN:同步标志 ACK:确认标志 FIN:结束标志)
(1)第一次握手:建立连接时,客户端发送SYN包(SYN=i)到服务器,并进入到SYN-SEND状态,等待服务器确认
(2)第二次握手:服务器收到SYN包,必须确认客户的SYN(ack=i+1),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器进入SYN-RECV状态
(3)第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认报ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手,客户端与服务器开始传送数据。
四次挥手:
(1)第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
(2)第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
(3)第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
(4)第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,Server收到并确认后,Server进入CLOSED状态,完成四次挥手。
6. GDI vs Direct2D
- 硬件加速 (硬件越新,加速越快,Direct2D全部都是硬件加速,而GDI和GDI+基本不靠硬件加速)
GDI将其资源(尤其是位图)保留在系统内存中,窗口内容的存储在视频内存表面。GDI使用CPU将大部分渲染执行到光圈存储器,当GDI需要更新窗口内容,也就是需要更新 视频内存时,除非资源已经在光圈存储器段中或者可以直接表示该操作,否则必须通过(bus)总线来完成,最后将结果发送回窗口表面。
而Direct2D就直接在显示适配器上的视频内存中维护其资源,然后将结果呈现在GPU上,然后发送到窗口表面。GDI也有部分api是在GPU上加速的,比如BitBlts,AlphaBlend,TransparentBlt和StretchBlt等。
- Direct2D完全在用户模式下运行。这有助于防止由于内核中的代码缺陷而导致系统崩溃。但是,GDI在内核模式下的会话空间中具有大部分功能,而在用户模式下则具有API界面。
- Direct2D的渲染调用都是到GPU的独立命令流。每个Direct2D工厂代表一个不同的Direct3D设备。GDI对系统上的所有应用程序使用一个命令流。GDI的方法可能导致GPU和CPU渲染上下文开销的累积。
- 校验和
- 序列号
- 确认应答
- 超时重传
- 连接管理
- 流量控制
- 拥塞控制
8. 虚拟内存(为什么要有虚拟内存)(好文章)
物理内存是有限的,多个进程要运行的时候,很显然内存不够分配。并且操作指令都是直接访问物理内存的,那么我这个进程就可以修改其他进程的数据,这是不合理的。
所以我们需要虚拟内存,进程运行时都会得到4G(32位)的虚拟内存,进程得到的这4G虚拟内存是一个连续的地址空间(这也只是进程认为),而实际上,它通常是被分隔成多个物理内存碎片,还有一部分存储在外部磁盘存储器上,在需要时进行数据交换。
进程开始要访问一个地址,它可能会经历下面的过程:(如果面试官问的特别仔细)
- 进程访问地址空间上的某一个地址,都需要把地址翻译为实际物理内存地址
- 所有进程共享这整一块物理内存,每个进程只把自己目前需要的虚拟地址空间映射到物理内存上
- 进程需要知道哪些地址空间上的数据在物理内存上,哪些不在(可能这部分存储在磁盘上),还有在物理内存上的哪里,这就需要通过页表来记录
- 页表的每一个表项分两部分,第一部分记录此页是否在物理内存上,第二部分记录物理内存页的地址(如果在的话)
- 当进程访问某个虚拟地址的时候,就会先去看页表,如果发现对应的数据不在物理内存上,就会发生缺页异常
- 缺页异常的处理过程,操作系统立即阻塞该进程,并将硬盘里对应的页换入内存,然后使该进程就绪,如果内存已经满了,没有空地方了,那就找一个页覆盖,至于具体覆盖的哪个页,就需要看操作系统的页面置换算法是怎么设计的了。
9. 纯虚函数只能被继承,无法被实例化。纯虚函数用来定义没有意义的实现,用于抽象类中需要交给派生类具体实现的方法。
因为虚函数都是采用的虚函数列表来进行的,如果是纯虚函数的话,该表指向一个不存在的函数,所以实例化被禁止。简单来说,就是 如果基类中含有纯虚函数,都不能实例化,在继承了该基类中的派生类中,如果不对该函数进行改写,也不能实例化。
小知识:纯虚函数还有利于检查基类的虚函数是否定义,比如有些时候我们使用虚函数光声明,但是没有定义的话,编译器就会报错。 使用了纯虚函数就不会报错了。
virtual void show() = 0; //纯虚函数
10. 虚函数列表的一些知识
一个类存在虚函数,那么编译器就会为这个类生成一个虚表,在虚表里存放的是这个类所有虚函数的地址。当生成类对象的时候,编译器会自动的将类对象的前四个字节设置为虚表的地址,而这四个字节就可以看作是一个指向虚表的指针。虚表里依次存放的是虚函数的地址,每个虚函数的地址占4个字节。
11. 广度优先搜索和深度优先搜索
这类概念经常在遍历文件或者遍历文件夹上用到。
12. 为什么需要内存对齐?
- 某些处理器只能存取对齐的数据,存取非对齐的数据可能会引发异常;
- 某些处理不能保证在存取非对齐数据的时候的操作是原子操作;
- 相比于存取对齐的数据,存取非对齐数据需要额外花费更多的时钟周期;
- 有些处理器虽然支持非对齐数据访问,但是会引发对齐陷阱;
- 某些处理只支持简单数据指令非对齐存取,不支持复杂数据指令非对齐存取。
总结起来就是两个大的原因:提升效率和避免出错。
13. C++中的static关键字
静态全局变量有以下特点:
- 该变量在全局数据区分配内存;
- 未经初始化的静态全局变量会被程序自动初始化为0(自动变量的值是随机的,除非它被显式初始化);
- 静态全局变量在声明它的整个文件都是可见的,而在文件之外是不可见的;
静态局部变量有以下特点:
(1)该变量在全局数据区分配内存;
(2)静态局部变量在程序执行到该对象的声明处时被首次初始化,即以后的函数调用不再进行初始化;
(3)静态局部变量一般在声明处初始化,如果没有显式初始化,会被程序自动初始化为0;
(4)它始终驻留在全局数据区,直到程序运行结束。但其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束;
关于静态成员函数,可以总结为以下几点:
- 出现在类体外的函数定义不能指定关键字static;
- 静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数;
- 非静态成员函数可以任意地访问静态成员函数和静态数据成员;
- 静态成员函数不能访问非静态成员函数和非静态数据成员;
- 由于没有this指针的额外开销,因此静态成员函数与类的全局函数相比速度上会有少许的增长;
- 调用静态成员函数,可以用成员访问操作符(.)和(->)为一个类的对象或指向类对象的指针调用静态成员函数,也可以直接使用如下格式:
<类名>::<静态成员函数名>(<参数表>)
调用类的静态成员函数。
网络上收集的C++常见面试题的更多相关文章
- iOS常见面试题汇总
iOS常见面试题汇总 1. 什么是 ARC? (ARC 是为了解决什么问题而诞生的?) ARC 是 Automatic Reference Counting 的缩写, 即自动引用计数. 这是苹果在 i ...
- JDBC常见面试题
以下我是归纳的JDBC知识点图: 图上的知识点都可以在我其他的文章内找到相应内容. JDBC常见面试题 JDBC操作数据库的步骤 ? JDBC操作数据库的步骤 ? 注册数据库驱动. 建立数据库连接. ...
- 整理的最全 python常见面试题(基本必考)
整理的最全 python常见面试题(基本必考) python 2018-05-17 作者 大蛇王 1.大数据的文件读取 ① 利用生成器generator ②迭代器进行迭代遍历:for line in ...
- java常见面试题及答案
java常见面试题及答案 来源 https://blog.csdn.net/hsk256/article/details/49052293 来源 https://blog.csdn.net/hsk25 ...
- HTTP、TCP、IP协议常见面试题
前言:在看面试题之前,先了解一下基本定义. HTTP.TCP.IP协议基本定义 HTTP: (HyperText Transport Protocol)是超文本传输协议的缩写,它用于传送WWW方式的数 ...
- python爬虫常见面试题(二)
前言 之所以在这里写下python爬虫常见面试题及解答,一是用作笔记,方便日后回忆:二是给自己一个和大家交流的机会,互相学习.进步,希望不正之处大家能给予指正:三是我也是互联网寒潮下岗的那批人之一,为 ...
- 整理的最全 python常见面试题
整理的最全 python常见面试题(基本必考)① ②③④⑤⑥⑦⑧⑨⑩ 1.大数据的文件读取: ① 利用生成器generator: ②迭代器进行迭代遍历:for line in file; 2.迭代 ...
- 【javascript常见面试题】常见前端面试题及答案
转自:http://www.cnblogs.com/syfwhu/p/4434132.html 前言 本文是在GitHub上看到一个大牛总结的前端常见面试题,很多问题问的都很好,很经典.很有代表性.上 ...
- 夯实Java基础系列16:一文读懂Java IO流和常见面试题
本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...
- 【搞定 Java 并发面试】面试最常问的 Java 并发进阶常见面试题总结!
本文为 SnailClimb 的原创,目前已经收录自我开源的 JavaGuide 中(61.5 k Star![Java学习+面试指南] 一份涵盖大部分Java程序员所需要掌握的核心知识.觉得内容不错 ...
随机推荐
- [转帖]TiDB 中的各种超时
https://docs.pingcap.com/zh/tidb/stable/dev-guide-timeouts-in-tidb 本章将介绍 TiDB 中的各种超时,为排查错误提供依据. GC 超 ...
- [转帖]kafka指定topic设置消息留存时间
背景 单个主题消息量庞大,需要指定这个主题的消息留存时间缩小点 执行命令 ./bin/kafka-configs.sh --bootstrap-server node1:9092 --entity-t ...
- [转帖]MioIO读/写性能测试
https://www.jianshu.com/p/a0a84f91b16f image.png COSBench是Intel团队基于java开发,是一个测试云对象存储系统的分布式基准测试工具,全 ...
- [转帖]一个Linux 内核 bug 导致的 TCP连接卡死
https://plantegg.github.io/2022/10/10/Linux%20BUG%E5%86%85%E6%A0%B8%E5%AF%BC%E8%87%B4%E7%9A%84%20TCP ...
- 获取特定端口java进程的路径的shell脚本
获取特定端口java进程的路径的shell脚本 ll /proc/`lsof -i:5200 |grep ^java |awk '{print $2}' |uniq` |grep cwd |cut - ...
- Stream流处理快速上手最佳实践
一 引言 JAVA1.8得益于Lambda所带来的函数式编程,引入了一个全新的Stream流概念Stream流式思想类似于工厂车间的"生产流水线",Stream流不是一种数据结构, ...
- element-ui表格展开行每次只能展开一行
element-ui表格展开行每次只能展开一行 <template> <el-table :data="tableData" :expand-row-keys=& ...
- Vue 中keep-alive组件将会被缓存
动态包裹哈 <keep-alive> <component :is="comName"></component> </keep-alive ...
- 动态添加input,然后获取所有的input框中的值
今天遇见一个问题. 点击按钮,动态添加input框(可以添加多个) 然后搜集用户在input中输入的值. 我刚刚在纠结,给input框中注入事件. 但是这样会很麻烦. 经过同事的指点. 我直接去拿v- ...
- TienChin 代码格式化-项目结构大改造
代码格式化 博主下载项目之后发现,整体的代码格式化风格,与 C 那种语言很相似,说明这个作者之前就是从事这块的导致风格有点类似,我们来格式化一下,当然这不是必要的,我是没习惯这种写法所以这里我写一下我 ...