1. 指针和引用的本质区别
指针和引用是C++中两个最基础也最容易混淆的概念。很多初学者在面试时会被这个问题卡住,其实只要从底层实现机制出发就很容易理解。
指针本质上是一个存储内存地址的变量。在x86-64系统上,指针变量固定占8字节(64位系统)。它有自己的内存空间,这个空间里存放的是另一个变量的地址。我们可以通过解引用操作符(*)来访问指针指向的内存。
引用则完全不同——它是已存在变量的别名。从汇编层面看,引用不会占用额外的存储空间,编译器会直接将其替换为原始变量的地址。这就是为什么引用必须在声明时初始化,且不能改变绑定的对象。
cpp复制int a = 10;
int* p = &a; // p是一个指针,存储a的地址
int& r = a; // r是a的别名,不占用额外内存
实际开发中最容易踩的坑是误用指针和引用作为函数参数。看这个典型例子:
cpp复制void modify(int* ptr, int& ref) {
*ptr += 1; // 必须解引用
ref += 1; // 直接操作原变量
}
int main() {
int x = 5;
modify(&x, x); // 指针需要取地址,引用直接传变量
cout << x; // 输出7
}
关键经验:当需要明确表示"可能为空"时用指针,需要确保对象存在时用引用。STL容器中只能存储指针不能存储引用,因为引用不是对象。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 野指针的成因与防御策略
野指针就像编程世界里的地雷——你不知道它什么时候会引爆。根据我的调试经验,野指针问题通常会在以下场景出现:
2.1 典型野指针场景分析
未初始化指针是最常见的初级错误:
cpp复制int* p; // 未初始化
*p = 42; // 灾难!
释放后使用在动态内存管理中很常见:
cpp复制int* arr = new int[100];
delete[] arr;
arr[50] = 1; // 访问已释放内存
返回局部变量指针是函数设计的大忌:
cpp复制int* createArray() {
int local[10];
