前言
什么是引用
Q:什么是引用? A:引用是已定义的变量的别名(另一个名称)。通俗来讲,就相当于起一个外号。
Q:引用语法是什么样的? A:语法:数据类型& 引用名 = 引用实体;
如果我们要将a 作为b 变量的别名,可以这样做:
int a;
int & b = a;
注意:& 不是地址运算符,而是类型标识符。它是放在数据类型后面的。
案例
#include <iostream>
using namespace std;
int main(void)
{
int a = 100;
int & b = a;
cout << a << endl;
cout << b << endl;
a++;
cout << a << endl;
cout << b << endl;
cout << &a << endl;
cout << &b << endl;
return 0;
}
运行结果:
结论: 通过观察运行结果,我们发现,a 与b 的值和地址都完全相同,将a 加一会同时影响到两个变量。
引用的特性
- 引用必须先进行初始化
引用不同于指针,必须要在声明引用前将其进行初始化,不能像指针一样,先声明,再赋值。
int a = 100;
int & b;
b = a;
- 引用一旦引用了一个实体,就不能引用其他实体
引用一但与一个实体关联起来,以后就不能进行改动了。 - 一个变量可以有多个引用
引用的作用
引用可以用作函数参数
Q:什么是按引用传递? A:引用经常被用作函数参数,让函数中的变量名成为调用程序中的变量的别名,这种传递参数的方法叫做按引用传递。按引用传递可以让被调用的函数访问调用函数中的变量。
案例
#include <iostream>
using namespace std;
void swap1(int &m, int &n) {
int temp = m;
m = n;
n = temp;
}
void swap2(int *m,int *n) {
int temp;
temp = *m;
*m = *n;
*n = temp;
}
int main(){
int a = 1, b = 100;
cout<<"before: a="<<a<<", b="<<b<<endl;
swap1(a,b);
cout<<"after: a="<<a<<", b="<<b<<endl;
swap2(a,b);
cout<<"after: a="<<a<<", b="<<b<<endl;
}
在这里我们将引用变量作为函数的形参,与指针作为形参类似,直接在函数内部对输入的参数进行修改,实现了交换操作。通过对比指针交换可以发现,引用变量在使用的时候比指针要简洁一些,变量本身就代表了引用的数据,而指针则需要加上* 。
引用可以用作函数返回值
在讲引用作为函数返回值之前,我们先了解一下传统的函数是如何传递返回值的吧。
普通传值返回
int Add(int a, int b) {
int c = a + b;
return c;
}
int main(void)
{
int ret = Add(1, 2);
cout << ret << endl;
return 0;
}
在这个例子里,return 时会生成一个临时变量,把c 的值赋给这个临时变量,再返回给ret 。 如果我们直接将c 返回给ret ,很难说返回的是3 还是随机值 ,一切都取决于编译器了。
Q:生成的临时变量存放在什么位置呢?
- A: 预备返回的变量小则用寄存器存储。
- A: 变量大则创建函数栈帧的时候预先为返回值创建存储空间。
引用传值返回
int &Add(int a, int b) {
int c = a + b;
return c;
}
int main(void)
{
int &ret1 = Add(1, 2);
cout << ret1 << endl;
return 0;
}
如果我们使用引用,那我们就不需要额外的临时空间和额外的操作,因为我们是通过引用直接对实体进行操作的,这可以很好的提高程序的效率。
引用与指针的区别
- 引用是在概念上定义一个变量的别名,而指针是存储一个变量的地址。
- 引用必须从一而终,不能再指向其他数据;指针可以随意改变指向。
- 引用在定义时必须初始化,而指针是最好初始化,不初始化也不会报错。
- 指针可以有多级,引用不可以。
- 存在空指针,但是不存在空引用。
|