C++ 引用和指针有什么区别?三种场景一次讲清

编程狮(w3cschool.cn) 2026-10-08 07:01:23 浏览数 (44)
反馈

C++ 引用和指针有什么区别?三种场景一次讲清

你刚学 C++ 时,是不是被引用和指针绕晕过:明明都能改到函数外面的变量,为什么有的地方用 int&、有的地方用 int*?核心答案一句话:当需要可空、可重新指向别处、或做地址运算时用指针;当只是给一个已经存在的对象起别名、且保证不为空时,引用更简洁也更安全。这篇基于 C++ 标准讲清二者在绑定、空值、运算上的本质差异,并给出选型清单。今天这篇文章,编程狮就把这块讲透。

先看结论

C++ 引用和指针都能间接访问对象,但约束不同。下表直接对齐“什么时候用谁”:

你的需求 首选 一句话理由
给对象起别名、不希望为空 引用 必须初始化且不可重绑定
可能暂无对象、需要判空 指针 可用 nullptr 表示空
遍历数组、做地址运算 指针 支持加减与解引用
函数参数避免拷贝 二者皆可 引用语法更干净

什么时候用引用,什么时候用指针

一、C++ 引用和指针的本质区别

指针本身是一个变量,它的值是另一个对象的地址。因为是指针是独立的变量,它有自己的地址,可以被重新指向别处,也可以暂时不指向任何东西。引用则不同,它是“已存在对象的别名”,定义时必须绑定到一个对象,之后无法再改指别的对象,并且标准上不存在“空引用”。

理解这两者的差异前,建议先过一遍 C++ 教程 把语法地基打平。这也是 C++ 面试里最高频的基础题,弄懂它基本就拿下了指针与引用这一关。

一句话区分:指针是“写着门牌号的纸条,可以涂改”;引用是“给这扇门贴的永久标签,贴上去就不能换门”。理解了这个比喻,后面所有差异都顺理成章。

⚠️ 注意:虽然引用底层常常用指针实现,但语义上它不是一个独立对象,不能像指针那样取它的地址再重新赋值。

二、指针的独门能力:空指针与指针运算

C++ 指针最不可替代的能力有两点:一是可以为空,用 nullptr 表示“现在还没有对象”;二是支持指针运算,尤其遍历数组时非常自然。代价是每次使用前都要判空,否则解引用空指针会直接崩溃。

int arr[3] = {10, 20, 30};
int* p = arr;        // 指向首元素
for (int i = 0; i < 3; ++i) {
    // 指针运算:p + i 指向第 i 个元素
    int value = *(p + i);
}
int* q = nullptr;    // 空指针,表示暂无对象
if (q != nullptr) {  // 使用前必须判空
    // 安全地解引用
}

这段先用指针加偏移量遍历数组,再演示空指针的定义与判空。指针运算让 p + i 直接跳到对应元素,是底层操作里离不开的工具。

三、引用的约束与安全优势

引用的约束恰恰是它的优点:必须初始化、不能为空、不能重绑定。这三点让编译器能替你排除一整类“空悬”错误。函数传参时用引用,既能避免拷贝大对象,又能直接修改原值,语法还比指针干净。

void increment(int& ref) {
    ref += 1;         // 直接改到原变量
}
int x = 41;
increment(x);         // x 变成 42

increment 接收 int&,调用时不需要取地址符,函数体里也像操作普通变量一样,但改的就是外面的 x。引用在运算符重载、范围 for 循环里几乎是标配。如果你从 C 语言转来,可以先看 C 语言教程 对比一下两者的内存模型。

C++ 引用与指针的五个核心区别

四、横向对比与选型建议

维度 引用 指针
是否可空 不可(语义上无空引用) 可,用 nullptr
是否可重绑定 不可,绑定后固定 可,随时改指向
是否支持运算 不支持 支持加减与偏移
语法负担 干净,像普通变量 需 * 解引用、& 取址
典型用途 参数别名、返回值 动态结构、数组、可空

踩坑清单

  1. 现象:引用绑定后还能改指别处;原因:误以为引用可重绑;修复:记住引用初始化后固定,要重绑请用指针。
  2. 现象:解引用直接崩溃;原因:指针未判空就 *;修复:凡是指针使用前都先 != nullptr。
  3. 现象:函数参数被意外修改;原因:传了引用却没意识到会改原值;修复:不需要修改就加 const int&。
  4. 现象:返回局部变量引用;原因:引用绑到了栈上临时对象;修复:不要返回局部变量的引用或地址。

总结

C++ 引用和指针的根本差异在“约束”:引用是必须初始化、不可空、不可重绑的别名,因此更安全也更省心;指针是可空、可重绑、可做地址运算的变量,因此更灵活也更危险。日常传参优先用 const 引用或引用,只有需要可空、遍历数组、或构建动态结构时才动用指针。

要点带走:

  • 引用语法干净且天然非空,是函数参数的首选;
  • 指针的空指针与指针运算无可替代,但每次使用都要判空;
  • 不要返回局部变量的引用或指针,那是最隐蔽的悬空错误。

下一步可以练手把项目里“只读不写”的参数改成 const 引用,既安全又高效。

动手验证清单

下面这组动作帮你在本机验证引用与指针行为,按你自己的环境执行,结果以实际输出为准(本文代码未在作者本机编译运行,仅给出预期形态):

  1. 安装:确认编译器支持 C++11,执行 g++ --version;
  2. 配置:用 g++ -std=c++11 ref.cpp -o ref 编译;
  3. 命令:写一段 int& 传参改值和 int* 判空的代码;
  4. 运行:./ref 观察修改是否反映到原变量;
  5. 检查:把指针设为 nullptr 后不解引用,确认不崩溃;
  6. 预期:引用修改直接生效,空指针判空后安全跳过;
  7. 失败:若运行时段错误,说明解引用了空指针,检查判空位置;
  8. 修复:所有指针解引用前加 nullptr 判断;
  9. 验证:把只读参数改成 const int&,确认无法在函数内被改写。

延伸学习

想把 C++ 基础补扎实,可以顺着这条线:

  1. 先过一遍 C++ 入门课程,把语法骨架搭起来;
  2. 分不清 C 与 C++ 时,看 C 和 C++ 的区别;
  3. 纠结语言选型就读 何时用 C 不用 C++。

常见问题

Q:引用和指针在底层是一回事吗?

A:大多数编译器确实用指针来实现引用,但语义层面完全不同。引用不是独立对象,不能取地址重新赋值,这些约束是编译器强制的,不属于底层实现细节。

Q:函数返回能用引用吗?

A:可以,但只能返回“生命周期长于函数”的对象,比如成员变量或静态变量。返回局部变量的引用会导致悬空,是严重错误。

Q:为什么推崇 const 引用做参数?

A:它既避免了大对象的值拷贝,又通过 const 保证函数内部不会误改原值,是兼顾性能与安全的默认写法。

0 人点赞