目录
一、基本概念
在C++中指针和引用都可以间接操作变量,但他们的语法和使用方式不一样。
引用的本质是:
欸已经存在的变量起一个别名。
指针的本质是:
存放变量地址的变量。
例如:
cpp
int a = 10;
int& ra = a; // 引用,ra是a的别名
int* p = &a; // 指针,p存放a的地址
二、引用的使用
引用定义的时候必须初始化。
cpp
int a = 10;
int ra = a;
这里ra和r指向同一块空间。
cpp
ra = 20;
cout << a << endl;
输出结果:
cpp
20
说明修改ra,其实就是修改a。
引用的特点是:
引用不是新变量,而是原变量的别名。
三、指针的使用
指针用来存放变量的地址。
cpp
int a = 10;
int* p = &a;
如果要通过指针修改变量,需要使用解引用操作符 *。
cpp
*p = 20;
cout << a << endl;
输出结果:
cpp
20
这里p保存的是a的地址,*p表示访问这个地址上的变量。
四、指针和引用的主要区别
1.引用必须初始化,指针可以不初始化
引用:
cpp
int a = 10;
int& r = a;
错误写法:
cpp
int& r; // 错误
指针:
cpp
int *p; // 可以定义,但不建议
指针虽然可以不初始化,但容易成为野指针,所以最好写成:
cpp
int *p = nullptr;
2.引用绑定后不能改变,指针可以改变指向
引用一旦绑定某个变量,就不能再改成其他变量的引用。
cpp
int a = 10;
int b = 20;
int& r = a;
r = b;
这里 r = b 不是让 r 改成引用 b,而不是 b 的值赋给 a。
执行后:
cpp
a = 20;
b = 20;
但 r 仍然是 a 的引用。
指针可以改变指向:
cpp
int a = 10;
int b = 20;
int* p = &a;
p = &b;
这里 p 一开始指向a,后来改成指向 b。
3.有空指针,没有空引用
指针可以为空:
cpp
int*p = nullptr;
但是引用必须绑定到一个已存在的变量。
cpp
int& r; // 错误
所以一般来说,引用会比指针安全一些。
4.sizeof结果不同
引用的 sizeof 结果是原变量类型大小。
cpp
int a = 10;
int& r = a;
cout << sizeof(r) << endl;
一般输出:
cpp
4
因为 r 是 a 的别名,所以 sizeof(r) 相当于sizeof(a)。
指针的sizeof结果是地址的大小。
cpp
int* p = &a;
cout << sizeof(p) << endl;
在32位环境下通常是4字节,在64位环境下通常是8字节。
5.指针需要解引用,引用可以直接使用
指针访问变量需要写 *p:
cpp
*p = 20;
引用可以想普通变量一样使用:
cpp
r = 20;
所以引用的语法更简单。
五、简单对比表
| 对比点 | 引用 | 指针 |
|---|---|---|
| 本质 | 变量的别名 | 存放地址的变量 |
| 初始化 | 必须初始化 | 可以不初始化 |
| 是否能改变指向 | 不能 | 可以 |
| 空值 | 没有空引用 | 可以为空指针 |
| 使用方式 | 直接使用 | 需要解引用 |
| sizeof | 原变量大小 | 地址大小 |
| 安全性 | 相对更安全 | 更灵活但风险更高 |
六、什么时候用引用,什么时候用指针?
如果只是函数传参、减少拷贝、或者希望语法更简单,一般优先考虑引用。
例如:
cpp
void Swap(int& x, int& y) {
int tmp = x;
x = y;
y = tmp;
}
如果需要可以表示"可能为空",或者需要动态改变指向,就更适合使用指针。
例如:
cpp
int* p = nullptr;
p = &a;
p = &b;
简单理解:
引用更安全、更简单;
指针更灵活,但容易出错。
七、小结
本篇主要学习了指针和引用的区别。
需要就记住:
- 引用是变量的别名;
- 指针是存放地址的变量;
- 引用必须初始化,指针可以不初始化。
- 引用绑定后不能改变,指针可以改变指向;
- 有空指针,没有空引用;
- 引用可以直接使用,指针需要解引用;
- 引用更安全,指针更灵活。
指针和引用都很重要。后面学习函数传参、类和对象、动态内存管理、数据结构时都会经常用到。