一、C++ 基础语法
1. 指针和引用的区别
相同点

不同点
表格
| 概念 | 存储变量的内存地址 | 已存在变量的别名 |
| 初始化 | 定义时无需初始化 | 定义时必须初始化 |
| 指向性 | 可随时指向同类型任意实体 | 初始化后不能引用其他实体 |
| 空值 | 存在 NULL 指针,操作需检查 | 无 NULL 引用,无需检查 |
| sizeof 含义 | 始终为地址空间字节数(32 位 4 字节) | 引用类型的实际大小 |
| 自加操作 | 指针向后偏移一个类型大小 | 引用的实体值 + 1 |
| 多级支持 | 支持多级指针(**p) | 无多级引用 |
| 访问方式 | 需显式解引用(*p) | 编译器自动处理,直接使用 |
| 安全性 | 相对较低,易出现野指针 | 相对更高 |
适用场景
- 指针:动态内存管理、实现复杂数据结构(链表、树等)
- 引用:操作符重载、返回引用实现链式调用
2. static 关键字
用于控制变量和函数的生命周期、作用域、访问权限,主要分为 4 类:
问题:解决不同编译单元 static 变量析构顺序不一致
- 问题根源:不同.cpp 文件的静态变量初始化顺序未定义,析构顺序与初始化相反,若 A 析构时依赖已析构的 B,程序崩溃
- 解决方案:静态局部变量 + 单例模式
- C++11 保证函数内局部静态变量初始化线程安全,且在 main 后首次调用时初始化
- 单例析构早于全局变量,即使析构后调用 getInstance (),其内存仍存在,可有限操作
3. inline 内联函数
4. new/malloc 与 delete/free 区别
new & malloc 核心区别
表格
| 失败处理 | 分配失败抛出异常 | 分配失败返回 NULL |
| 内存大小 | 自动计算,无需指定 | 需显式指定字节数 |
| 类型处理 | 自动推导类型,无需强转 | 返回 void*,需强制类型转换 |
| 重载支持 | operator new/delete 可重载 | 不可重载 |
| 对象处理 | 调用构造 / 析构函数 | 仅分配 / 释放内存,不处理对象 |
| 语言属性 | C++ 运算符 | C 标准库函数 |
delete & free 核心区别


delete[]如何知道要析构多少元素?
new[]分配内存时,会分配size_t大小的空间,用于存储数组元素个数 delete[]p; 指针左偏移sizeof(size_t)就可以拿到数组个数,从而知道析构多少元素
5. 函数指针和指针函数
函数指针
- 指向函数的指针变量,存储函数地址,支持运行时动态调用函数
- 语法:返回值类型 (*指针名)(参数列表) = &函数名;
- 示例:
int add(int a, int b) { return a+b; }
int (*ptr)(int,int) = &add;
int res = (*ptr)(3,4); // 调用结果为7 - 适用场景:回调函数、动态加载库的函数调用
指针函数
- 返回值为指针类型的普通函数,本质是函数,非指针
- 语法:返回值类型* 函数名(参数列表);
- 注意:避免返回局部变量的指针(局部变量出作用域销毁,会产生野指针)
6. 强制类型转换
C++ 提供 4 种显式类型转换,替代 C 语言的隐式转换,更安全、语义更清晰:
表格
| static_cast | 基本类型转换、上行转换(派生→基类)、任意类型转 void | 中等 | 无运行时类型检查,下行转换(基类→派生)不安全 |
| dynamic_cast | 存在虚函数的父子类之间的下行转换 | 高 | 有运行时类型检查;指针转换失败返回 nullptr,引用失败抛出异常 |
| reinterpret_cast | 任意指针 / 引用间转换、指针与整型转换 | 最低(最危险) | 仅重新解释二进制位,不做类型检查 |
| const_cast | 移除变量的 const/volatile 属性 | 中等 | 仅修改常量性,不改变类型;常量指针→非常量指针,仍指向原对象 |






