指针和引用绝对是 C/C++ 面试的 “拦路虎”!不管是应届生还是社招,笔试面试中总能遇到 “指针初始化错误”“引用不能为空”“const 指针区别” 这类题,看似基础却藏着超多陷阱,不少技术人栽在上面丢分。今天拆解指针与引用的高频真题、易错点和避坑技巧,帮你吃透基础分,笔试面试不踩雷~一、核心区别:指针 vs 引用,4 个关键点分清!
这是面试必考题,记住 “本质不同 + 使用场景差异”,再也不会混淆:面试真题
“指针和引用的核心区别是什么?分别在什么场景使用?”正确答案(4 点核心)
非空特性:引用不能指向空值,必须初始化时绑定某个对象;指针可以为空(NULL),也能后续赋值指向不同对象。
合法性检查:使用引用前无需判断合法性(肯定指向有效对象);指针必须检查是否为空,否则容易触发野指针错误。
可修改性:引用一旦绑定对象,不能改绑其他对象(但对象内容可改);指针可以随时重新赋值,指向不同内存地址。
内存开销:引用本质是对象的别名,不占用额外内存;指针存储内存地址,占用 4 字节(32 位)或 8 字节(64 位)内存。
适用场景
用引用:确定变量必指向有效对象、无需改绑(比如函数参数传递,避免拷贝);
用指针:可能为空、需要动态指向不同对象(比如链表节点遍历、动态内存分配)。
避坑技巧
面试中遇到这类题,先讲核心区别,再结合场景举例,比如 “函数参数用引用传递 string,避免拷贝开销;链表操作用指针,方便移动指向”,答案更完整。二、高频坑 1:指针未初始化 = 野指针,程序崩溃预警!
面试真题(错误代码)
#include
using namespace std;
int main() {
int *pi; // 指针未初始化
*pi = 10; // 给未初始化的指针赋值
cout << *pi << endl;
return 0;
}
问题:这段代码会发生什么?
A. 输出 10 B. 编译报错 C. 程序崩溃 D. 随机值正确答案:C
解析:
指针 pi 未初始化时,指向的是随机内存地址(野指针),给随机地址赋值会触发内存访问错误,直接导致程序崩溃。避坑技巧
指针声明时必须初始化:要么指向有效变量(int a=0; int *pi=&a;),要么设为 NULL(int *pi=NULL;);
使用指针前先判断是否为空:if (pi != NULL) { *pi = 10; },避免野指针操作。
三、高频坑 2:引用必须初始化,否则编译报错!
面试真题(错误代码)
#include
using namespace std;
int main() {
int &ref; // 引用未初始化
int a=5;
ref = a; // 试图后续绑定对象
cout << ref << endl;
return 0;
}
问题:这段代码会编译通过吗?
A. 会,输出 5 B. 编译报错 C. 运行时崩溃 D. 输出随机值正确答案:B
解析:
引用的核心规则是 “必须在声明时初始化”,不能先声明再绑定对象。上面的代码中,int &ref; 未初始化,编译器直接报错。正确写法
int a=5;
int &ref = a; // 声明时直接绑定a
避坑技巧
记住 “引用 = 别名”,就像给人起外号,必须先有人(对象)才能起外号,不能先起外号再找人绑定,这是引用的语法铁律。四、高频坑 3:const 修饰指针,3 种情况别搞混!
const 和指针结合是面试高频考点,3 种写法差异极大,记错就丢分:面试真题
const int *p;
int const *p;
int *const p;
正确解析
1 和 2 完全相同:const 修饰的是 * p(指针指向的内容),意思是 “指向的内容不能改”,但指针可以改指向;示例:const int *p=&a; *p=10;(错误,内容不能改);p=&b;(正确,指针可改指向);
3:const 修饰的是 p(指针本身),意思是 “指针不能改指向”,但指向的内容可以改;示例:int *const p=&a; p=&b;(错误,指针不能改指向);*p=10;(正确,内容可改)。
记忆技巧
const 靠近 * p → 内容不能改;
const 靠近 p → 指针不能改。
避坑技巧
面试中遇到 const 指针题,先判断 const 修饰的是 “指针本身” 还是 “指向的内容”,再逐一分析选项,避免凭感觉选错。五、高频坑 4:函数参数传递,指针 vs 引用的区别!
面试真题
正确答案
引用无需检查空值,使用更安全(指针可能传 NULL,需额外判断);
引用语法更简洁(无需写 & 取地址、* 解引用);
引用本质是别名,无额外内存开销,和指针效率一致,但更易读。
反例(指针传递的问题)
void func(int *p) {
if(p == NULL) return; // 必须额外判断空值
*p = 10;
}
// 调用时
int a=5;
func(&a); // 需手动取地址
正例(引用传递)
void func(int &ref) {
ref = 10; // 无需判断,直接使用
}
// 调用时
int a=5;
func(a); // 直接传变量,语法简洁
避坑技巧
传递简单类型(int、char):指针和引用区别不大;
传递大对象(结构体、类对象):优先用引用(安全 + 简洁);
传递可能为空的对象:只能用指针(引用不能为 NULL)。
六、笔试易错点汇总(直接背!)
引用必须初始化,指针可以未初始化(但不推荐);
野指针是指针未初始化或指向已释放的内存,会导致程序崩溃;
const int *p 和 int const *p 等价,都是内容不可改;
引用不能改绑对象,但可以修改对象的内容(比如 int &ref=a; ref=10; 正确);
函数返回局部变量的引用会导致未定义行为(局部变量销毁后,引用指向无效内存)。