目录
一、引用的概念
二、应用特性
三、常引用
四、使用场景
引用不是重新定义一个变量,而是给一个已经存在的变量取了一个别名,编译器不会为了应用变量去开辟一个空间,但是别名和那个存在的变量共享一个内存空间。
比如:李逵在家叫“铁牛”,在江湖上称作“黑旋风”。
引用的符号为“&”
使用案例
void TestRef()
{
int a=10;
int &ra=a;
printf("%p\n",a);
printf("%p",ra);
}
测试结果:
说明它们所调用的是同一个空间。
void Test()
{
int a = 10;
printf("%d\n", a);
int& ra = a;
printf("a=%d,ra=%d", a, ra);
}
测试结果:
说明一个变量和他的引用权限是一样的,就像你叫李逵和叫他黑旋风效果是一样的。
引用类型必须和引用实体是同种类型的。
1.引用在定义时必须初始化,因为它在定义后是无法改变自己的引用变量的。
2.一个变量可以有多个引用,一个人也可以有多个小名。
3.引用一旦引用一个实体就不能再引用别的实体了。
void TestRef()
{
int a=10;
int &ra=a;
int &rra=a;
printf("%p %p %p ",a,ra,rra);
}
测试结果:
const int a=10;
int &ra=a;
这一段代码会引发报错
原因是:a只能读不能写,但是你写了一个引用ra想把它从一个只能读取的变量变成能读能写的变量。
原理:引用一个变量,你可以在权限层次上平移权限,也可以将权限缩小了引用。
这段代码应该改为:
const int a=10;
const int &ra=a;
权限缩小怎么缩小呢:
int a=10;
const int &ra=a;
常引用还有一个比较重要的用法,用来存储常量:
void Test()
{
int a = 0;
double d = 12.34;
a = d;
}
这一段代码虽然在编译器不会报错而且也能成功编译,但是你知道这是什么原理吗
double类型数据d在传送给a之前会进入临时空间,然后a变量再在临时空间取数据,这样子就会数据截断,在a存入12。
这个临时空间具有常性,所以下面这段代码会报错:
void Test3()
{
int &a=10;
}
因为10其实也是一个临时空间里的数据,临时空间具有常性需要用const的引用来装这个数据。
1.做参数
void Swap(int& left, int& right)
{
int temp = left;
left = right;
right = temp;
}
这个其实类似于指针,指针传送地址进来,函数里的值改变,函数外的值也随之改变。引用把变量的别名传进来,也就相当于将变量的使用权传进来了。
2.做返回值
int& Count()
{
static int n = 0;
n++;
// ...
return n;
}
int main()
{
int ret=Count();
return 0;
}
引用做返回值有一个好处,可以提高程序效率。
调用Test4函数结束后,它的函数栈也会销毁,变量n也会不存在了。那我们是怎么在函数结束后将返回值返回给ret的呢?编译器会在内存中申请一个寄存器存放n的值,再将值传给ret。
但是在Count函数里,是没有这一个过程的,static会将n存放在另一个空间,在函数栈销毁后依然存在,这是直接返回引用值可以直接将n的值返回给ret2,这样就可以省去中间的步骤,提高效率。