指针 vs 引用 (Pointer vs Reference)
核心摘要:指针是一个存放地址的变量,而引用是原变量的别名。
在 C++ 中,指针和引用都可以间接访问对象,但它们在行为和使用场景上有本质区别。
🔍 主要区别
| 特性 | 指针 (Pointer) | 引用 (Reference) |
|---|---|---|
| 本质 | 变量:存储的是另一个变量的内存地址 | 别名:原变量的另一个名字,不占独立内存(通常) |
| 空值 (Null) | 可以为空 (nullptr) | 必须绑定对象,不存在空引用 |
| 初始化 | 定义时可以不初始化 (不推荐) | 定义时必须初始化 |
| 重指向 | 可以改变指向 (指向不同的对象) | 不可改变 (一旦绑定,终身不换) |
| 语法操作 | 需要解引用 (*p),访问成员用 -> | 直接像普通变量一样使用,访问成员用 . |
| 算术运算 | 支持指针运算 (如 p++ 移动地址) | 不支持 (对引用做运算是修改原值) |
| 多级嵌套 | 有多级指针 (int**) | 没有引用的引用 (但有右值引用 &&) |
| sizeof | 指针本身的大小 (4或8字节) | 引用对象的大小 |
💻 代码示例
1. 初始化与重指向
cpp
int a = 10;
int b = 20;
// --- 指针 ---
int* p = &a; // 初始化指向 a
p = &b; // ✅ 合法:可以改为指向 b
p = nullptr; // ✅ 合法:可以为空
// --- 引用 ---
int& r = a; // 初始化绑定 a
r = b; // ⚠️ 陷阱:这不是让 r 指向 b,而是把 b 的值(20)赋值给 r 绑定的对象(a)
// 此时 a 变成了 20,r 依然是 a 的别名
// int& r2; // ❌ 编译错误:引用必须初始化2. 作为函数参数
- 指针传参:如果参数可能为空,或者需要改变指针本身的指向(极少),用指针。
- 引用传参:C++ 中更推荐的方式。如果不需要处理空值,优先使用
const T&(只读) 或T&(修改)。
cpp
// 指针版本 (调用者需要传地址,内部需要判空)
void addOnePtr(int* p) {
if (p) (*p)++;
}
// 引用版本 (调用者直接传变量,内部不需要判空,代码更洁)
void addOneRef(int& r) {
r++;
}
int main() {
int x = 10;
addOnePtr(&x); // 传地址
addOneRef(x); // 传变量,就像操作 x 本身一样
}🧠 什么时候用哪个?
- 优先使用引用:在函数参数传递、返回值、范围
for循环中,引用更安全、语法更简洁。 - 必须使用指针的场景:
- 对象可能不存在 (需要
nullptr表示)。 - 需要指针算术运算 (如数组遍历)。
- 需要在运行时改变指向的对象。
- 与 C 语言接口兼容时。
- 对象可能不存在 (需要
总结
- 指针与引用最主要的区别:指针是一个独立的变量,存放对象的地址,可以不依赖于对象存在;引用是对象的别名,必须要绑定到对象中,且一旦绑定就不可修改
