【C++入门】(十四)创建引用
-
引用是一个别名。
-
创建引用时,使用另一个对象(目标)的名称来初始化它,从此以后,该引用就像是目标的另一个名称,对引用执行的任何操作实际上针对的就是目标
-
必须区分: 指针是存储另一个对象的地址的变量;而引用是对象的别名
2. 引用和指针的差别是什么?
-
区别在于:指针存储的是对象地址的变量;
引用存储的是对象的别名
-
引用相当于目标的另一个名称,对引用执行的任何操作实际上影响的都是目标
-
引用提供了指针的强大威力,但语法更简单
2.1 空指针和空引用
-
指针未初始化或被删除时,应将 nullptr 赋给它
-
但让引用指向空对象的程序是非法的,而在非法的程序中什么神秘的bug都有可能发生
-
虽然,大多数编译器都支持空引用,但如果将程序移植到其他计算机或编译器上时,神秘的bug就出现了
2.2 既然指针能够完成引用的所有功能,为何还要使用引用?
-
引用更容易使用和理解。
-
引用的间接关系被隐藏,无需不断解除引用
2.3 既然引用更容易,为何要使用指针?(套娃了属于是)
-
引用不能为空,也不能重新赋值。
-
指针提供了更大的灵活性,但使用起来更难
3. 如何创建和使用引用?
3.1 创建引用
-
创建引用,需要指定目标对象的类型、引用运算符(&)、引用名
int a; int& rname = a; //目标对象的类型 &引用名 = 变量 (创建指向变量 a 的引用) int a; int& rname = a; //引用必须初始化(指向变量a) a = 5; cout << "变量a: " << a << endl; //变量a: 5 cout << "引用: " << rname << endl; //引用: 5 rname = 7; //实际上是将 7 赋值给了 a(引用是 a 的别名) cout << "变量a: " << a << endl; //变量a: 7 cout << "引用: " << rname << endl; //引用: 7
-
引用运算符(int& rname = a;)
和地址运算符(int *p = &a;)
是同一个符号&
;
-
声明指针时,星号
*
表示声明的变量是指针(int *p = NULL;)
;而在语句中与指针一起使用时,星号也表示间接运算符/解引用(YourAge = *pAge;)
;星号还能用于数学表达式中,表示乘法运算(a * b;)
3.2 将地址运算符用于引用
-
如果请求返回引用的地址,就将返回它指向的目标的地址
int a; int& rname = a; a = 5; cout << "变量a: " << a << endl; //变量a: 5 cout << "引用: " << rname << endl; //引用: 5 cout << "&变量a: " << &a << endl; //&变量a: 000000AFFA3EFCF4 cout << "&引用: " << &rname << endl; //&引用: 000000AFFA3EFCF4
-
不能给引用重新赋值,它始终是目标变量的别名(永远指向原来变量的地址)
int a; int& rname = a; a = 5; cout << "变量a:\t" << a << endl; //变量a: 5 cout << "引用:\t" << rname << endl; //引用: 5 cout << "&a:\t" << &a << endl; //&a: 0000007FAF95F894 cout << "&rname:\t" << &rname << endl; //&rname: 0000007FAF95F894 int b = 8; rname = b; // 此处,对引用的赋值,相当于 a = b,引用地址仍忠诚指向a的地址 cout << "变量a:\t" << a << endl; //变量a: 8 cout << "变量b:\t" << b << endl; //变量b: 8 cout << "引用:\t" << rname << endl; //引用: 8 cout << "&a:\t" << &a << endl; //&a: 0000007FAF95F894 cout << "&b:\t" << &b << endl; //&b: 0000007FAF95F8D4 cout << "&rname:\t" << &rname << endl; //&rname: 0000007FAF95F894
4. 引用的局限性是什么?
4.1 可引用的目标
-
可引用任何对象,包括用户定义的对象
//注意:创建的是指向对象的引用,而不是指向类或数据类型的对象 int& rname = int; //报错,不能指向数据类型 Cat& rname = Cat; //报错,不能将引用初始化为 Cat 类
-
必须将引用初始化为指定特定的 int 变量:
int a = 10; int& rname = a;
-
或将引用初始化为指定特定的 Cat 对象:
Cat a; Cat& rname = a;
-
可以像使用对象那样使用指向对象的引用:用类成员访问运算符
.
来访问成员数据和成员函数:class cat { public: int func1() { return 100; } }; int main() { cat a; cat& rname = a; cout << "rname.func1():" << rname.func1() << endl; //rname.func1(): 100 cout << "a.func1():" << a.func1() << endl; //a.func1(): 100 return 0; }
5. 如何按引用将值和对象传入和传出函数?
5.1 按引用传递函数参数
-
函数的两个局限性:参数按值传递; return 语句只能返回一个值
通过将值按引用传递给函数,可消除这两种局限性
-
在C++中,按引用传递是通过两种方式完成的:使用指针和使用引用。
它们语法不同,但效果相同:不是在函数作用域内创建备份,而是将原始对象传递给函数
void swap(int x, int y); int main() { int x = 5, y = 10; cout << "Main函数中,初始值 x=" << x << " y=" << y << endl; //Main函数中,初始值 x=5 y=10 swap(x, y); cout << "Main函数中,调用后 x=" << x << " y=" << y << endl; //Main函数中,调用后 x=5 y=10 return 0; } void swap(int x, int y) { int temp = x; x = y; y = temp; cout << "Swap函数中, 交换值 x=" << x << " y=" << y << endl; //Swap函数中, 交换值 x=10 y=5 } //按值传递函数,值只在函数里面交换,并没有修改原来的变量
-
使用指针实现 swap()
传入指针时,传递的实际上是对象的地址,因此函数可操作该地址处的值
void swap(int* x, int* y); int main() { int x = 5, y = 10; cout << "Main函数中,初始值, x=" << x << " y=" << y << endl; //Main函数中,初始值, x=5 y=10 swap(&x, &y); cout << "Main函数中,调用后,x=" << x << " y=" << y << endl; //Main函数中,调用后,x=10 y=5 return 0; } void swap(int* px, int* py) { int temp; temp = *px; *px = *py; *py = temp; cout << "Swap函数中,交换后,*px=" << *px << " *py=" << *py << endl; //Swap函数中,交换后,*px=10 *py=5 } //使用指针,修改了原来的变量(交换覆盖了地址,进而改变了变量的值)
-
使用引用实现 swap()
上面的代码虽修改了原来的变量,但需要不断的解引用,这很容易翻车,可读性也不好,为此使用引用:
void swap(int& x, int& y); int main() { int x = 5, y = 10; cout << "Main函数中,初始值, x=" << x << " y=" << y << endl; //Main函数中,初始值, x=5 y=10 swap(x, y); cout << "Main函数中,调用后,x=" << x << " y=" << y << endl; //Main函数中,调用后,x=10 y=5 return 0; } void swap(int& rx, int& ry) { int temp; temp = rx; rx = ry; ry = temp; cout << "Swap函数中,交换后, rx=" << rx << " ry=" << ry << endl; //Swap函数中,交换后,*px=10 *py=5 } //按引用传递函数,修改了原来的变量
5.2 返回多个值
-
一般条件下,函数只能返回一个值;
如果需返回多个值,可通过引用修改原始对象的值,这相当于让函数返回多个值
short factor(int, int*, int*); //传指针 int main() { int a = 10; int b, c; factor(a, &b, &c); cout << "a: " << a << endl; //a: 10 cout << "b: " << b << endl; //b: 100 cout << "c: " << c << endl; //c : 1000 return 0; } short factor(int A, int* pB, int* pC) { *pB = A * A; *pC = A * A * A; //使用传递给函数的指针直接进行数据的修改 return 0; } short factor(int, int&, int&); //传引用 int main() { int a = 10; int b, c; factor(a, b, c); cout << "a: " << a << endl; //a: 10 cout << "b: " << b << endl; //b: 100 cout << "c: " << c << endl; //c : 1000 return 0; } short factor(int A, int& rB, int& rC) { rB = A * A; rC = A * A * A; //使用传引用,更易理解和维护 return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具