C++ 面试基础高频重灾区,笔试、代码题、口头追问全覆盖,话术标准、踩分点明确,可直接背诵答题。
1. 指针和引用的区别
- 本质不同:指针是独立变量,存放内存地址;引用是变量别名,底层依托指针实现,无独立语义。
- 初始化规则 :指针可延迟初始化、可置空;引用定义时必须初始化,不存在空引用。
- 指向修改 :指针可随时更改指向不同内存;引用一旦绑定变量,终身无法重新绑定。
- 内存占用:指针占用 4/8 字节(由系统位数决定);引用不占用额外内存空间。
- 使用风险:指针易出现空指针、野指针问题;引用安全性高,无野引用。
- 使用语法 :指针需配合
*解引用、&取地址;引用直接使用,语法更简洁。
高频追问
问 :引用底层是指针,为什么还要设计引用?
答:屏蔽指针的安全隐患,简化书写语法,适合函数传参、返回值等场景。
2. 野指针成因、危害与规避
一、核心成因
- 指针未初始化,指向随机未知内存。
- 指向的内存被释放(栈变量出作用域、堆内存执行
delete/free),指针未及时置空。 - 指针访问越界,指向合法内存之外的地址。
二、主要危害
访问非法内存,造成程序崩溃、数据篡改、逻辑错乱。属于未定义行为,问题随机出现,排查难度极大。
三、工程规避方案
- 指针定义时直接初始化为
nullptr。 - 内存释放后,立刻将对应指针置空。
- 校验指针有效性与数组下标,杜绝越界访问。
- 优先使用引用、智能指针替代原生指针。
3. 空指针、空引用详解
3.1 空指针
- 定义:指向
0地址或nullptr的指针,不指向任何有效内存。 - 特性:语法合法,严禁解引用,解引用会直接导致程序崩溃。
- 用途:标记指针无有效指向,常用于判空做逻辑分支。
3.2 空引用
- C++ 语法层面不存在合法空引用,引用定义时必须绑定有效变量。
- 特殊场景:将空指针强制转为引用,会产生非法引用,本质等同于野指针,运行必然崩溃。
面试结论
空指针语法合法,禁止解引用;空引用不被语法允许,出现即为代码 BUG。
4. 常量指针 vs 指针常量
记忆口诀:看const靠近谁,谁就不能修改
- 常量指针
const int* pconst修饰指向的内容,指针指向的值不可修改,指针自身地址可修改。
- 指针常量
int* const pconst修饰指针本身,指针地址不可修改,指向的值可以修改。
- 双重 const
const int* const p- 指针地址、指向内容均不可修改,完全只读。
速记
左定值,右定址 :const在*左侧,值不可改;const在*右侧,地址不可改。
5. 多级指针使用场景
核心定义
二级及以上指针,即指向指针的指针,层级代表间接访问的层数。
主流使用场景
- 管理动态二维数组、不规则数组。
- 函数内修改外部一级指针,需传入二级指针作为参数。
- 存储字符串数组,典型用法
char**。 - 底层接口、系统 API 的输出型参数。
补充说明
三级及以上指针可读性极差,工程开发中尽量避免使用。
6. 数组指针与指针数组区分
记忆口诀:看括号内括号归指针,无括号归数组
- 指针数组
int* arr[N]- 本质:数组 ,数组内每一个元素都是
int*类型指针。 - 用途:存放一组指针、字符串数组。
- 本质:数组 ,数组内每一个元素都是
- 数组指针
int (*p)[N]- 本质:指针,专门指向长度为 N 的整型数组。
- 用途:操作、遍历二维数组。
原理补充
运算符优先级:[] 高于 *。无括号时,变量先和[]结合为数组;加括号后,变量先和*结合为指针。
7. 函数指针与回调函数
7.1 函数指针
- 定义:指向函数的指针,存储函数的入口地址。
- 作用:可像普通变量一样传递、调用函数。
- 标准格式:
返回值类型 (*指针名)(参数列表)
7.2 回调函数
- 定义:将函数指针作为参数传入其他函数,由对方在指定时机自动调用该函数。
- 核心思想:实现代码解耦,分离调用方与功能实现方。
典型场景
事件监听、异步处理、自定义排序规则、第三方库接口、系统底层调用。
8. this 指针底层原理
8.1 基础定义
this是类成员函数隐含形参,指向当前调用该函数的对象本身。
8.2 核心特性
- 由编译器自动生成、自动传递,用户不用手动传参。
- 存储位置:一般存放在栈区 / 寄存器,不属于对象成员,不占用对象内存。
- 静态成员函数没有 this 指针,因为静态函数不属于某个对象。
8.3 作用
- 区分成员变量与局部变量 / 形参(解决命名冲突)。
- 在成员函数中访问当前对象的成员。
- 链式调用返回当前对象
return *this。
面试坑点
空对象调用普通成员函数,若函数不访问成员变量,可能不崩溃;一旦通过this访问成员,程序直接崩溃。
9. 指针运算规则
指针运算仅适用于数组 / 连续内存,普通变量指针不建议做运算。
- 指针 ± 整数 并非单纯数值加减,而是偏移对应类型的字节大小 。例:
int* p,p+1会偏移一个int所占字节。 - 指针 - 指针 仅同一块连续内存内合法,计算结果为两个指针之间的元素个数,非字节数。
- 指针比较运算 同数组内指针可使用
>,<,==判断大小,常用于遍历边界判断。
禁止操作
指针之间不能相加、相乘、相除,语法无实际意义,属于非法代码。
10. 指针传参 vs 值传递
1. 值传递
- 机制:实参拷贝副本传给形参,函数内仅操作副本。
- 特点:原数据不受影响;大数据拷贝开销大,执行效率低。
- 适用场景:仅读取数据,无需修改原变量。
2. 指针传参
- 机制:传递变量内存地址,函数通过地址直接操作原数据。
- 特点:无需拷贝,效率高;可修改外部实参;存在指针安全风险。
- 适用场景:需要修改原变量、传递大型对象减少拷贝开销。
补充:引用传参
引用传参等价于指针传参的语法优化,效率一致、安全性更高,工程中优先使用。
🔥 综合高频追问(背诵版)
-
问 :数组名和数组首元素指针有什么区别?
答 :数组名是常量指针,不能修改指向;普通指针可修改。
sizeof(数组名)获取数组总大小,sizeof(指针)固定为 4/8 字节。 -
问 :野指针和空指针哪个危害更大?
答:野指针行为随机、崩溃无规律,排查难度远高于空指针,危害更大。
-
问 :为什么静态成员函数没有 this 指针?
答:静态成员隶属于类,而非单个对象,因此不需要指向对象的 this 指针。
📝 模块总结
本模块是 C++ 语法根基,围绕指针分类、语法规则、底层原理、工程使用、传参机制展开。吃透全部内容,可应对笔试选择、代码阅读、面试口述中 90% 以上指针相关题目。
