在C++函数参数传递中,引用和指针是两种常用方式,它们都能让函数间接操作外部变量,但在语法语义和内存管理方面存在本质区别。引用是已存在变量的别名,而指针是存储地址的独立变量,理解这些差异有助于写出更安全的代码。

基本概念对比
引用在声明时必须初始化并绑定到一个对象,之后不能重新绑定。指针可以不初始化,也能在生命周期内指向不同地址,甚至为空。下面通过表格说明核心差异:
| 特性 | 引用 | 指针 |
|---|---|---|
| 是否占用独立内存 | 通常不与对象分开存储 | 自身占内存保存地址 |
| 可否为空 | 不允许空引用 | 可为nullptr |
| 可否重新指向 | 不可 | 可以 |
代码示例说明
以下代码展示引用与指针作为函数参数的不同写法:
#include <iostream>
using namespace std;
// 引用传递:形参是实参的别名
void add_by_ref(int &x) {
x = x + 10;
}
// 指针传递:形参保存实参地址
void add_by_ptr(int *x) {
if (x != nullptr) { // 必须检查空指针
*x = *x + 10;
}
}
int main() {
int a = 5;
int b = 5;
add_by_ref(a);
add_by_ptr(&b);
cout << "a=" << a << ", b=" << b << endl;
return 0;
}
内存管理上的影响
引用本身不引入额外对象,因此不会像指针那样因忘记释放或重复释放造成内存问题。指针如果指向通过new分配的堆内存,调用方必须明确谁负责释放:
- 若函数内
delete指针,调用方不应再使用原指针,否则成野指针。 - 若仅用指针读取值而不管理生命周期,需保证指向对象在函数外有效。
- 引用常用来避免拷贝大对象,又比指针安全,因为不存在空引用。
动态内存场景
当函数接收指针并涉及动态分配时,建议使用智能指针而非原始指针,以减少手动管理负担:
#include <memory>
using namespace std;
// 使用智能指针避免裸指针内存泄漏
void process(unique_ptr<int> p) {
// 函数结束自动释放
}
使用建议
对于不需要重新指向且不应为空的参数,优先使用引用传递,代码清晰且安全。对于可选参数、需要修改指向或兼容C接口的场景,使用指针并做好空值检查。合理选择能降低内存管理风险,提升程序稳定性。