33.引用-引用的基础使用
33.1 知识点
什么是引用
引用是对已有变量的别名,它允许我们通过另一个名字来访问变量。与我们之前学过的 &
符号用于取地址操作不同,在引用声明中,&
用于声明一个变量的别名。
以下是引用的基础语法:
变量类型& 引用名 = 表达式;
int a = 10;
// 创建一个引用 refA,它是变量 a 的别名
int& refA = a;
// 输出变量 a 的值
cout << "变量 a 的值:" << a << endl; // 输出结果:10
// 输出变量 a 的地址
cout << "变量 a 的地址:" << &a << endl; // 输出结果:变量 a 的实际地址
// 输出引用 refA 的值
cout << "引用 refA 的值:" << refA << endl; // 输出结果:10
// 输出引用 refA 的地址
cout << "引用 refA 的地址:" << &refA << endl; // 输出结果:变量 a 的实际地址
// 通过引用 refA 修改变量 a 的值
refA = 20;
// 输出修改后的变量 a 的值
cout << "修改 refA 后,变量 a 的值:" << a << endl; // 输出结果:20
使用引用的注意事项
引用对象必须初始化
引用对象在声明时必须被初始化,例如:
int& refB = a; // refB 是 a 的引用
引用变量的类型必须与引用内容类型一致
引用的类型与被引用变量的类型必须一致。例如:
// 以下代码会导致编译错误,因为 short 类型和 int 类型不匹配
// short& refS = a; // 编译报错
// short& refS = (short)a; // 强转也会编译报错
引用绑定的对象不能更改
引用一旦绑定到某个变量,就不能更改为引用另一个对象。例如:
int b = 99;
// 这里不是修改引用 refB 所指向的对象,而是修改 refB 所引用的变量的值
// 引用一旦绑定,就不能绑定到另一个对象上,这里只是将 a 的值修改为 b 的值
refB = b;
// 输出变量 a 的值,它应该是 99,因为我们将 b 的值赋给了 refB(也就是 a)
cout << "执行 refB = b 后,变量 a 的值:" << a << endl; // 输出结果:99
引用不会占用新的内存空间
引用只是原变量的别名,不会单独占用内存空间。例如:
// 动态分配一个整数内存,存储值为 66
int* p = new int(66);
// 创建一个引用 refP,它是指针 p 所指向的内存空间的引用
int& refP = *p;
// 输出指针 p 的地址
cout << "指针 p 的地址:" << p << endl; // 输出结果:指针 p 所指向的内存地址
// 输出指针 p 所指向的内存空间的值
cout << "指针 p 所指向的值:" << *p << endl; // 输出结果:66
// 输出引用 refP 的地址,它应该与 p 的地址相同,因为 refP 是 *p 的别名
cout << "引用 refP 的地址:" << &refP << endl; // 输出结果:指针 p 所指向的内存地址
// 输出引用 refP 的值,它应该与 *p 的值相同,因为 refP 是 *p 的别名
cout << "引用 refP 的值:" << refP << endl; // 输出结果:66
// 释放动态分配的内存
delete p;
// 将指针 p 置为 nullptr,以避免悬空指针
p = nullptr;
// 此时,refP 可以被称为悬空引用,因为它所引用的内存已被释放,使用它可能会导致未定义行为
// 但 C++ 不会阻止你这样做,所以需要特别注意,尽量避免这种情况
引用和指针的区别
引用必须被初始化,且不能更改指向
int* p2 = nullptr; // 指针可以为空
p2 = &a; // 指针可以重新指向另一个变量
p2 = &b; // 再次改变指向
cout << "指针 p2 所指向的值:" << *p2 << endl; // 输出结果:99
引用更安全
引用不能是 nullptr
,不存在空引用的问题。此外,引用在使用时会自动解引用,语法更简洁:
int& refA = a;
cout << refA << endl; // 无需使用 * 运算符
指针支持加减运算
指针可以通过加减运算改变所指向的位置,而引用不支持这种操作:
p2++; // 指针可以移动指向
// 引用 refA 不允许类似操作
总结
引用是一种方便、安全的变量别名,可以避免直接操作指针的复杂性。但由于引用绑定不可更改且不能为 nullptr
,它适用于需要稳定引用的场景。而指针更灵活,适合需要动态调整指向的情况。
33.2 知识点代码
Lesson33_引用_引用的基础使用.cpp
#include <iostream>
using namespace std;
int main()
{
std::cout << "引用的基础使用\n";
#pragma region 知识点一 什么是引用
// 解释引用的概念:引用是对已有变量的别名,它允许我们通过另一个名字来访问变量
// 这里说明 & 符号的另一个作用是声明引用,而不仅仅是我们之前学过的取地址操作
// 在指针赋值时,& 用来获取变量的地址,而在引用声明中,& 用来声明一个变量的别名
// 以下是引用的基础语法:变量类型& 引用名 = 表达式;
int a = 10;
// 创建一个引用 refA,它是变量 a 的别名
int& refA = a;
// 输出变量 a 的值
cout << "变量 a 的值:" << a << endl; // 输出结果:10
// 输出变量 a 的地址
cout << "变量 a 的地址:" << &a << endl; // 输出结果:变量 a 的实际地址
// 输出引用 refA 的值,它应该与 a 的值相同,因为 refA 是 a 的别名
cout << "引用 refA 的值:" << refA << endl; // 输出结果:10
// 输出引用 refA 的地址,它应该与 a 的地址相同,因为 refA 是 a 的别名
cout << "引用 refA 的地址:" << &refA << endl; // 输出结果:变量 a 的实际地址
// 通过引用 refA 修改它所引用的变量 a 的值
refA = 20;
// 再次输出变量 a 的值,应该显示为 20,因为我们通过 refA 修改了它
cout << "修改 refA 后,变量 a 的值:" << a << endl; // 输出结果:20
#pragma endregion
#pragma region 知识点二 使用引用的注意事项
// 1. 引用对象必须初始化,这里将 refB 初始化为 a 的引用
int& refB = a;
// 2. 引用变量的类型必须和引用的内容类型一致
// 以下这行代码会导致编译错误,因为 short 类型和 int 类型不匹配
// short& refS = a;//编译报错
// short& refS = (short)a;//强转也编译报错
// 3. 引用绑定的对象不能更改
int b = 99;
// 这里不是修改引用 refB 所指向的对象,而是修改 refB 所引用的变量的值
// 引用一旦绑定,就不能绑定到另一个对象上,这里只是将 a 的值修改为 b 的值
refB = b;
// 输出变量 a 的值,它应该是 99,因为我们将 b 的值赋给了 refB(也就是 a)
cout << "执行 refB = b 后,变量 a 的值:" << a << endl; // 输出结果:99
// 4. 引用不会占用新的内存空间,只是原变量的另一种名称而已
// 动态分配一个整数内存,存储值为 66
int* p = new int(66);
// 创建一个引用 refP,它是指针 p 所指向的内存空间的引用
int& refP = *p;
// 输出指针 p 的地址
cout << "指针 p 的地址:" << p << endl; // 输出结果:指针 p 所指向的内存地址
// 输出指针 p 所指向的内存空间的值
cout << "指针 p 所指向的值:" << *p << endl; // 输出结果:66
// 输出引用 refP 的地址,它应该与 p 的地址相同,因为 refP 是 *p 的别名
cout << "引用 refP 的地址:" << &refP << endl; // 输出结果:指针 p 所指向的内存地址
// 输出引用 refP 的值,它应该与 *p 的值相同,因为 refP 是 *p 的别名
cout << "引用 refP 的值:" << refP << endl; // 输出结果:66
// 释放动态分配的内存
delete p;
// 将指针 p 置为 nullptr,以避免悬空指针
p = nullptr;
// 此时,refP 可以被称为悬空引用,因为它所引用的内存已被释放,使用它可能会导致未定义行为
// 但 C++ 不会阻止你这样做,所以需要特别注意,尽量避免这种情况
#pragma endregion
#pragma region 知识点三 引用和指针的区别
// 1. 引用必须被初始化并且不可以修改指向,而指针可以为空并随时可以切换指向
int* p2 = nullptr;
// 让指针 p2 指向变量 a 的地址
p2 = &a;
// 让指针 p2 指向变量 b 的地址,指针可以重新赋值,改变其指向
p2 = &b;
// 输出指针 p2 所指向的变量 b 的值
cout << "指针 p2 所指向的值:" << *p2 << endl; // 输出结果:99
// 2. 引用更安全,因为引用不能是 nullptr,不存在空引用的问题
// 而且引用在使用时会自动解引用,不需要使用 * 运算符来获取所引用变量的值,语法更简洁清晰
// 3. 指针可以进行加减运算移动指向位置,例如 p2++; 这样的操作是允许的
// 但引用不可以进行这样的操作,因为引用不是存储地址的变量,它只是别名
#pragma endregion
}
33.3 练习题
使用引用时有哪些注意事项?
- 引用对象必须初始化
- 引用变量的类型必须和引用的内容类型一致
- 引用绑定的对象不能更改
- 引用不会占用新的内存空间,只是原变量的另一种名称而已
- 等等
引用和指针的区别?
定义和绑定
- 引用:是一个已存在变量的别名,在定义时必须绑定到一个对象,并且绑定后不能更改。
- 指针:指针是一个变量,存储的是对象的内存地址,可以随时指向不同的对象。
语法和使用
- 引用:不需要解引用操作符
*
去取值,直接像变量一样操作即可。 - 指针:需要通过解引用操作符
*
取值。
是否可以为空
- 引用:初始化时必须绑定,不能为空。
- 指针:可以为空,表示不指向任何对象。
是否可以自增减
- 引用:不行。
- 指针:可以,可以通过自增减操作移动指针指向内存地址。
内存占用
- 引用:不单独占用内存,访问引用时会直接对源对象进行访问。
- 指针:指针是一个变量,独立占用内存,用于存储地址。
其它
- 等等
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com