C++中要理解「指针的引用」,我们需要先拆解两个基础概念:指针和引用,再看它们结合后的作用 —— 核心是「通过引用操作指针本身」。
一、先明确两个基础概念
1. 指针(T*)
- 本质:一个变量,存储的是另一个变量的「内存地址」。
- 用途:通过地址间接访问 / 修改目标变量。
- 示例:
int a = 10; int* p = &a; // p是指针,存储a的地址 *p = 20; // 通过指针修改a的值(a变成20)
2. 引用(T&)
- 本质:目标变量的「别名」,不是新变量,和目标变量共用同一块内存。
- 用途:直接操作目标变量(比指针更简洁、安全)。
- 规则:必须初始化(绑定一个变量),一旦绑定不能改绑。
- 示例:
-
int a = 10; int& ref = a; // ref是a的别名,和a同内存 ref = 20; // 直接修改a的值(a变成20)
二、指针的引用(T*&)
定义:
「指针的引用」是 指针变量的别名—— 它不是指向变量的引用,而是指向「指针本身」的引用。语法:类型*& 引用名 = 指针变量名;(*& 连写,明确是 “指针的引用”)
核心作用:
通过引用直接操作「指针变量本身」(比如修改指针的指向、修改指针存储的地址),而不是通过指针操作目标变量。这和普通指针参数(T*)的区别是:普通指针参数传递的是指针的「拷贝」,而指针的引用传递的是指针的「别名」,修改会直接作用于原指针。
三、为什么需要指针的引用?
核心优势是:要通过函数直接操作主函数中的指针(或其指向的数组),避免拷贝。
我们用对比来理解:假设要写排序函数,有两种参数传递方式:
方式 1:普通指针参数(double* arr)
- 传递的是指针的「拷贝」:函数内部的
arr是主函数arr的副本,两者存储的地址相同(所以能通过arr[j]访问原数组),但指针本身是两个独立变量。 - 局限:函数内部无法修改主函数中指针的「指向」(比如让主函数的
arr指向新数组),只能修改指针指向的「目标数据」(数组元素)。 - 示例:
// 普通指针参数:只能修改数组元素,不能修改指针本身 void sort1(double* arr, int n) { arr = new double[5]; // 修改的是拷贝指针的指向,主函数的arr不受影响 // 排序逻辑... } int main() { double* arr = new double[3]{1.1, 2.2, 3.3}; sort1(arr, 3); // 传递的是arr的拷贝 delete[] arr; // 主函数的arr仍指向原数组,正常释放 }
方式 2:指针的引用参数(double*& arr)
- 传递的是指针的「别名」:函数内部的
arr和主函数的arr是同一个指针变量,修改会直接作用于主函数的指针。 - 优势:既可以通过
arr[j]修改数组元素(和普通指针一样),也可以修改指针本身(比如让主函数的arr指向新地址) - 示例:
-
// 指针的引用参数:直接操作主函数的指针 void sortDesc(double*& arr, int n) { // 冒泡排序:修改的是arr指向的数组元素(主函数的数组会同步变化) for (int i = 0; i < n-1; i++) { for (int j = 0; j < n-1-i; j++) { if (arr[j] < arr[j+1]) { swap(arr[j], arr[j+1]); // 直接修改原数组元素 } } } } int main() { double* arr = new double[5]{3.2, 5.4, 6.12, 2.51, 4.23}; sortDesc(arr, 5); // 传递arr的引用(别名) // 主函数的arr指向的数组已被排序,直接输出即可 }
四、指针引用的关键应用场景
场景 1:修改指针的指向(主函数中指针指向新地址)
#include <iostream>
using namespace std;
// 指针的引用:修改主函数中指针的指向
void changePtr(double*& ptr) {
static double b = 99.9; // 静态变量,地址固定
ptr = &b; // 修改指针的指向(主函数的ptr会同步指向b)
}
int main() {
double a = 10.5;
double* p = &a; // 初始:p指向a
cout << "修改前:*p = " << *p << endl; // 输出10.5
changePtr(p); // 传递p的引用(别名)
cout << "修改后:*p = " << *p << endl; // 输出99.9(p已指向b)
return 0;
}
场景 2:避免指针拷贝(提升效率)
当指针指向的是大数组 / 大对象时,传递指针的引用无需拷贝指针(虽然指针本身占用内存小,但逻辑上更直接),且能确保操作的是原指针。
五、常见误区(避坑!)
-
语法误区:
T*&不能写成T&*(语法错误)。- 原因:C++ 运算符优先级中,
&(引用)比*(指针)低,T&*会被解析为「指向引用的指针」,但引用不是变量,没有地址,所以不允许。
- 原因:C++ 运算符优先级中,
-
用途误区:不要用指针的引用 “多此一举”。
- 若只需通过指针修改「目标变量 / 数组元素」,普通指针(
T*)足够; - 若需要修改「指针本身」(比如改变指针指向、给指针重新分配内存),才需要指针的引用(
T*&)。
- 若只需通过指针修改「目标变量 / 数组元素」,普通指针(
-
和 “指向引用的指针” 区分:
- 指针的引用(
T*&):合法,是指针的别名; - 指向引用的指针(
T&*):非法,引用无地址,无法被指针指向。
- 指针的引用(
总结
| 类型 | 语法 | 核心作用 | 适用场景 |
|---|---|---|---|
| 普通指针 | T* | 操作指针指向的「目标变量」 | 间接访问 / 修改目标数据 |
| 指针的引用 | T*& | 操作「指针本身」(别名) | 修改指针指向、避免指针拷贝 |
| 普通引用 | T& | 操作「变量本身」(别名) | 直接访问 / 修改变量(替代指针) |
简单记:
- 想改「目标数据」→ 用普通指针(
T*)或普通引用(T&); - 想改「指针本身」→ 用指针的引用(
T*&)。
1842

被折叠的 条评论
为什么被折叠?



