C++面试总结




C++ 面试总结
一、语言基础
1.1 指针
智能指针
指针和引用的区别
数组、指针区别
数组指针、指针数组区别
迭代器、指针区别
strcpy 和 memcpy 区别
1.2 内存管理与分配
内存分配与存储区
malloc / free
、 区别
volatile extern
拷贝构造函数
预处理、编译、汇编、链接
define/const/typedef/inline 区别
、 区别
const static
声明和定义的区别
1.3 编程特性
C++11新特性
C 和 C++ 区别
C++ 和 Java 区别
C++ 和 Pyhton 区别
1.4 类与面向对象
初始化
重载、重写以及重定义的区别
四种强制类型转换
结构体和类的区别
类的大小 与 内存对齐
1
面向对象三大特征
虚函数
1.5 基础概念
简述 fork/wait/exec 函数
1.6 STL
模板
vector
list
deque
priority_queue
map 和 set
hashtable
1.7 算法
memcpy 实现
读写锁
死锁复现代码
二叉树序列号与反序列化
生产者消费者模式
二叉树-前中后迭代算法模板
手写智能指针
十大排序算法(升序实现)
二、计算机网络
2.1 OSI 七层模型
2.2 TCP/IP 四层模型
2.3 TCP 和 UDP
TCP 协议
TCP 流量控制
TCP 拥塞控制
TCP 三次握手
TCP 四次挥手
TCP 粘包问题
TCP Socket交互流程
2
UDP 协议
2.4 HTTP
HTTP 请求方法
HTTP 状态码
HTTP 缓存
HTTP 报文格式
Cookie 和 Session 区别
Session 的实现原理
HTTP/1.1
HTTP/2.0
HTTP/3 / QUIC
2.5 HTTPS
SSL/TLS
RSA密钥交换算法
ECDHE 密钥交换算法
2.6 DNS
2.7 IP
2.8 WebSocket
2.9 DHCP
2.10 NET
2.11 IGMP
三、操作系统
3.1 用户态 和 内核态
执行系统调用时 OS 状态
CPU 中断
零拷贝
3.2 进程、线程、协程
进程与线程区别
线程的实现方式
线程安全
线程的同步方式
进程状态
3
进程/CPU调度算法
进程的分类
进程间的通信方式
协程
3.3 锁
类型
死锁
3.4 虚拟内存
虚拟地址空间
虚拟内存实现思路
内存管理方法
页面放置算法
页面置换算法
磁盘调度算法
内存不足会发生什么
3.5 缓存区
缓存区溢出
3.6 I/O 模型
I/O 模型类型
I/O 复用模型
Reactor 与 Proactor 模式
3.7 Copy on Write
3.8 Linux
启动过程
常用命令
3.9 硬件结构
CPU 缓存一致性
伪共享
一致性哈希
四、数据库 / MySQL
4.1 三大范式
4.2 数据库引擎
4
Innodb
MyISAM
4.3 数据库索引
索引分类
索引优缺点
索引使用场景
优化索引方法
数据库为什么用 B+ 树做索引
联合索引与最左匹配原则
count(...) 查询效率
4.4 关系型数据库、非关系型数据库
关系型数据库(SQL)
非关系型数据库(NOSQL)
4.5 数据库连接池
4.6 事务
ACID 特性 与 实现
两阶段提交
隔离性问题
隔离级别
4.7 数据库中的锁
意向锁(Intention Locks)
多版本并发控制(MVCC)
4.8 查询优化方法
mysql 深度分页
4.9 主从复制
五、设计模式
5.1 设计原则
5.2 常用设计模式
单例模式
简单工厂模式
模板方法
责任链模式
5
装饰器模式
六、Redis
6.1 基本数据结构(底层实现)
SDS
链表
字典
跳跃表
整数集合
压缩列表
6.2 对象
字符串对象
列表对象
哈希对象
集合对象 set
有序集合对象 zset
6.3 数据库
RDB 持久化
AOF 持久化
数据淘汰策略
6.4 客户端与服务器
复制
Sentinel(哨兵)
集群
6.5 事务
6.6 缓存管理
缓存穿透
缓存击穿
缓存雪崩
6.7 高并发系统设计
一、语言基础
6
1.1 指针
野指针:指针指向的位置是不可知的
悬空指针:指针最初指向的内存已经被释放了的一种指针
两种指针都指向无效内存空间,即不安全不可控。需要在定义指针后且在使用之前完成初始化或者使用
智能指针来避免
智能指针
智能指针的 作用 是管理指针,避免使用普通指针申请的空间在函数结束时忘记释放,造成内存泄漏。
因为智能指针是一个类,当超出类的作用域时,类会自动调用析构函数,析构函数有释放资源的操作。
类型:
● auto_ptr 采用所有权模式(C11已弃用),使得一个该类型指针可以剥夺另一个该类型指针的所有
权,使得被剥夺所有权的指针失效,缺点是使用被剥夺的指针存在潜在的内存崩溃问题。
● unique_ptr 实现独占式拥有,保证同一时间内只有一个智能指针可以指向该对象,避免上述内存崩
溃的出现。只能通过 new 来创建。
● shared_ptr 实现共享式拥有,可以用 new 来构造,还可以引入其他智能指针来构造。多个智能指
针可以指向相同的对象,该对象和其相关资源会在最后一个引用(use_count() 查看引用数)被销
毁时释放。当调用 release() 时,当前指针会释放资源所有权,计数减一。当计数等于0 时,资源
会被释放。资源消耗大,因为创建时会调用两次new(其中一次是引用计数对象)
● weak_ptr 是一种不控制对象生命周期的智能指针,它指向一个 shared_ptr 管理的对象。进行该对
象内存管理的是 shared_ptr,weak_ptr 只是提供了对管理对象的一个访问方法,目的是为了协助
shared_ptr 工作,它只可以从一个 shared_ptr 或另一个 weak_ptr 对象构造,且不会引起引用计
数值的变化。主要用来解决 空悬指针 和 循环引用 问题。空悬指针是两个共享指针同时引用同一个
对象,但是其中一个指针将该对象销毁,另一个指针会指向为空,可通过使用 weak_ptr 来判断指
向对象是否有效;循环引用是指两个对象之间相互引用,则引用计数将无法减为0,而其中一方改
为 weak_ptr 则可检测是否有效,且能将有效的指向对象转换为共享指针进行操作。[1] [2]
指针和引用的区别
● 指针和引用都是一种内存地址的概念,但是指针是一个实体,可以声明为 void;引用只是一个别
名,不能为 void。
● 引用内部其实是一个指针,引用比指针更安全;相对的,引用没有指针灵活。
● 引用和指针都可以作为参数传递给函数,用于更改函数作用域外的变量,在传递大对象时避免复
制,提升效率。作为参数时也有不同,传递指针的实质是传值,传递的值是指针的地址;传引用的
实质是传地址,传递的是变量的地址。
● 指针可以有多级指向,但是引用只能有一级引用。
7
● 引用是一块内存的别名,在添加到符号表时,是将“引用变量名-引用对象的地址”添加到符号表
中,符号表一经完成不能改变,所以引用只能在定义时被绑定到一块内存上,后续不能更改引用对
象。指针指向一块内存,其值是所指向的内存的地址,在编译的时候,则是将“指针变量名-指针变
量的地址”添加到符号表中,所以指针包含的内容是可以改变的,允许拷贝和赋值。
数组、指针区别
1. 数组存放的是数据,是直接访问数据的;指针存放的是变量的地址,是间接访问数据的;
2. 数组通常存储在静态存储区或栈上;指针可以随时地指向任意类型的内存块;
3. 用运算符 sizeof 可以计算出数组的容量(字节数);sizeof(p) 得到的是一个指针变量 p 的字节
数,而不是 p 指针所指向的内存容量;
4. char a[] = "hello" 数组指向每个数组元素;char *p = "hello" 而 p 指向字符串首地址;
数组指针、指针数组区别
数组指针(指向数组的指针)
1. 数组在内存中的表示:创建一个数组就是在内存里面开辟一块连续的空间;
1 int a[2][2] = {1,2,3,4}; // 这是一个2*2的二维数组
2 数组指针
int (*p)[2]; //
3 令 指向数组
p = a; // p a
指针数组(存放指针的数组)
指针数组的好处:
迭代器、指针区别
迭代器:用于提供一种方法顺序访问一个聚合对象中各个元素,而又无需暴露该对象的内部表示。
迭代器和指针区别:迭代器不是指针,是类模板,表现的像指针,其本质是封装了原生指针,提供了比
指针更高级的行为,相当于一种智能指针,可以根据不同类型的数据结构来实现递增、递减等操作。迭
代器返回的是对象引用而不是对象的值
strcpy 和 memcpy 区别
● 复制的内容不同。strcpy 只能复制字符串,而 memcpy 可以复制任意内容,例如字符数组、整
型、结构体、类等;
● 复制的方法不同。strcpy 不需要指定长度,它遇到被复制字符串的结束符 "