指针与引用高频坑!大厂笔试 80% 错题都在这,看完直接提分
- 2026-10-23 00:00:16
一、核心区别:指针 vs 引用,4 个关键点分清!
面试真题
正确答案(4 点核心)
非空特性:引用不能指向空值,必须初始化时绑定某个对象;指针可以为空(NULL),也能后续赋值指向不同对象。
合法性检查:使用引用前无需判断合法性(肯定指向有效对象);指针必须检查是否为空,否则容易触发野指针错误。
可修改性:引用一旦绑定对象,不能改绑其他对象(但对象内容可改);指针可以随时重新赋值,指向不同内存地址。
内存开销:引用本质是对象的别名,不占用额外内存;指针存储内存地址,占用 4 字节(32 位)或 8 字节(64 位)内存。
适用场景
用引用:确定变量必指向有效对象、无需改绑(比如函数参数传递,避免拷贝);
用指针:可能为空、需要动态指向不同对象(比如链表节点遍历、动态内存分配)。
避坑技巧
二、高频坑 1:指针未初始化 = 野指针,程序崩溃预警!
面试真题(错误代码)
using namespace std;
int main() {
int *pi; // 指针未初始化
*pi = 10; // 给未初始化的指针赋值
cout << *pi << endl;
return 0;
}
问题:这段代码会发生什么?
正确答案:C
解析:
避坑技巧
指针声明时必须初始化:要么指向有效变量(int a=0; int *pi=&a;),要么设为 NULL(int *pi=NULL;);
使用指针前先判断是否为空:if (pi != NULL) { *pi = 10; },避免野指针操作。
三、高频坑 2:引用必须初始化,否则编译报错!
面试真题(错误代码)
using namespace std;
int main() {
int &ref; // 引用未初始化
int a=5;
ref = a; // 试图后续绑定对象
cout << ref << endl;
return 0;
}
问题:这段代码会编译通过吗?
正确答案:B
解析:
正确写法
int a=5;
int &ref = a; // 声明时直接绑定a
避坑技巧
四、高频坑 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 → 指针不能改。
避坑技巧
五、高频坑 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; 正确);
函数返回局部变量的引用会导致未定义行为(局部变量销毁后,引用指向无效内存)。