C++八股(面试题、手撕题)自用版

目录

面试题: 

1. define inline 在编译的哪个阶段

2. const static

3. 子函数返回结构体有什么问题,返回对象调用了哪些函数

4. volatile关键字

5. 编译器基本原理

6. 预处理、编译、汇编、链接以及他们在操作系统上如何运作的

7. 数组和指针(二维)

8. 指针和引用

9. new 和 malloc

10.万能引用和右值引用

11. 解释中断,以及底层发生的操作细节

12. C++多线程在操作系统上如何运作的

13. 进程、线程间通信方式

14. 信号量在操作系统中如何实现

15. 虚函数

16. 构造函数、析构函数

17. C++内存管理

18. 智能指针

手撕题:

1. 内存池

2. lambda表达式

3. 手写单例模式

4. 遍历二叉树(非递归)

5. 实现一个简易的shared_ptr


面试题: 

1. define inline 在编译的哪个阶段

define: 预编译/预处理

inline: 链接阶段

2. const static

经过static修饰的变量会作为类的属性而不是实体属性存在。它的作用是在编译时期确定,程序运行过程中不会改变。

static 关键字用于声明静态成员变量、静态成员函数和局部静态变量,其作用取决于它所修饰的实体。

  • 静态成员变量:静态成员变量是属于类的,而不是属于类的各个实例的。它的特点是所有类的实例共享同一份静态成员变量。静态成员变量可以通过类名直接访问,也可以通过对象访问。
  • 静态成员函数:静态成员函数是属于类的函数,它不依赖于任何特定的对象。因此,它可以直接通过类名来调用,而不需要创建类的实例
  • 局部静态变量:具有静态生存期,即它在程序运行期间只初始化一次,并且在函数调用结束后仍然存在于内存中。

const

const 关键字用于声明常量,它指定了一个变量在初始化后不能被修改的特性。const 可以用于变量、成员函数和指针。

3. 子函数返回结构体有什么问题,返回对象调用了哪些函数

typedef定义类型,因此返回return mm类似返回int这种基础操作,仅需声明函数时也声明结构体的类型。

也可以用指针

4. volatile关键字

volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。

5. 编译器基本原理

6. 预处理、编译、汇编、链接以及他们在操作系统上如何运作的

1、预处理:

通过gcc -E main.c -o main.i    生成.i文件将进行如下操作:

1、将所有的#define删除,并展开所有的宏定义。

2、处理所有的预编译指令,例如:#if,#elif,#else,#endif等。

3、处理#include预编译指令,将被包含的文件插入到预编译指令的位置。

4、添加行号信息、文件名标识,便于调试。

5、删除所有的注释。

6、保留所有的#pragma编译指令,因为在编写程序的时候,我们经常要用到#pargma指令来设定编译的状态或者是指示编译器完成一些特定的动作。

7、生成.i文件(包括去注释、宏替换、头文件展开、条件编译),编译生成的.i文件不包含任何宏定义,因为宏已经被展开,并且包含的文件已经被插入到.i文件中。

2、编译(C/C++语音 ------> 汇编):

通过gcc -S main.i –o main.s    生成.s文件,需要进行如下操作:

1、扫描、语法分析、语义分析、源代码分析、目标代码生成、目标代码优化。

2、生成汇编代码。

3、汇总符号。

4、生成.s文件。

3、汇编(汇编 ------> 二进制):

通过gcc –c main.s –o main.o   生成.o文件,需要进行如下操作:

1、根据汇编指令和特定平台,把汇编指令翻译成二进制形式。

2、合并各个section,合并符号表。

3、生成.o文件。

4、链接:

链接过程会进行如下操作:

1、合并各个.obj文件的section,合并符号表,进行符号解析。

2、符号地址重定位。

3、生成可执行文件。

7. 数组和指针(二维)

二维数组名是一个二级指针?

8. 指针和引用

指针大小固定,初始化需要分配内存,指针指向的地址可变

引用为变量的别名,需要初始化,初始化后不可改变

存在空值的指针,不存在空值的引用

9. new 和 malloc

new delete 操作符
malloc free 函数

常规八股

要了解new的底层需要熟悉operator操作符

怎样减少内存碎片--->内存池

10.万能引用和右值引用

涉及类型推导的引用,才会是万能引用。

对于万能引用,如果采用右值来初始化,得到的是一个右值引用,如果采用左值来初始化万能引用,那么得到的是一个左值引用。

左值引用能引用左值和右值,右值引用只能引用右值

Move的功能是将一个左值引用强制转化为右值引用,继而可以通过右值引用使用该值,以用于移动语义,从实现原理上讲基本等同一个强制类型转换。

优点:可以将左值变成右值而避免拷贝构造,将对象的状态所有权从一个对象转移到另一个对象,只是转移,没有内存搬迁或者内存拷贝。

11. 解释中断,以及底层发生的操作细节

中断:CPU  中端服务程序

识别中断源、找到中断程序、保存当前任务的各个寄存器状态、进入中断处理程序后的返回等

...

对于外部中断,CPU在执行当前指令的最后一个时钟周期去查询INTR引脚,若查询到中断请求信号有效,同时在系统开中断(即IF=1)的情 况下,CPU向发出中断请求的外设回送一个低电平有效的中断应答信号,作为对中断请求INTR的应答,系统自动进入中断响应周期(即中断响应指令的指令周期)。

不太详细...

12. C++多线程在操作系统上如何运作的

  • 多线程实现:C++标准库提供了对多线程的支持,开发人员可以使用 std::thread 等类来创建和管理线程。C++11引入了对并发编程的支持,包括原子操作、互斥量、条件变量等,使得线程间的同步和通信更加方便。此外,还有一些其他的第三方库,如Boost.Thread等,也提供了丰富的多线程支持。
  • 多进程实现:在C++中,可以使用操作系统提供的系统调用或者一些跨平台的库来创建和管理多个独立的进程。例如,可以使用fork()系统调用来创建一个新的进程,或者使用exec()系列函数来在新的进程中执行其他程序。另外,一些跨平台的库,如Boost.Interprocess等,也提供了一些跨平台的进程间通信的工具,如共享内存、消息队列等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值