引用并非定义一个新的变量,而是为一个已经存在的变量起一个别名
虽然底层是通过指针实现的,但是和指针不一样,无需另外开辟空间,在某些场景下,使用引用可以减少拷贝
目录
(3)区别五:使用引用无需开辟空间,但是指针需要通过开空间,被赋予空间地址
一、引用的定义
数据类型& 别名 = 实体名
=》这里的 & 不是取地址,相当于指针声明时的 *,标识现在声明的是一个引用变量
int main()
{
int a = 10;
int& b = a; //这里的& 代表声明一个引用
int* p = &a; //这里的& 代表取地址
}
二、引用的特性
1、 引用的时候必须初始化
既然是起别名,那么使用引用就必须要知道为谁 起别名
int main(){
int a = 10;
int& b = a; //为a起别名,或者说绑定的实体是a
return 0;
}
2、 引用只能绑定一个实体
如果b绑定了实体 a,再去绑定实体 c,那么使用b的时候,应该使用哪个实体呢
3、 一个实体可以有多个引用(别名)
在家可以有小名,在外可以有绰号,在公司可以有职称
int main(){
int a = 10,c = 20;
int& b = a; //b绑定的实体是a
int& c = a; //c绑定的实体是a
//b、c都是a的引用,相当于b是在家的小名,c是在外的绰号
return 0;
}
三、引用的应用场景
1、引用传参
最简单的例子就是交换两个变量的值
//通过引用 交换两个变量的值
void Swap(int& x,int& y)
{
int tmp = x;
x = y;
y = tmp;
}
int main(){
int a = 10,b = 20;
Swap(a,b);
return 0;
}
在调用Swap函数时,一一对应原则,把 a 给了Swap的第一个参数,相当于 int& x = a
x 这个时候就可以看作是a的别名,改变 x 就可以改变 a
y 也是同理
当然,如果这里使用指针的话,可以达到同样的效果
// 通过指针交换两个变量的值
void Swap(int* x, int* y)
{
int tmp = *x;
*x = *y;
*y = tmp;
}
int main(){
int a = 10,b = 20;
Swap(&a,&b);
return 0;
}
2、引用返回
详见我的另一篇博客
四、指针和引用的区别
1、概念的角度
引用 =======》 一个变量的别名
指针 =======》 一个变量的地址
2、初始化的角度
(1)区别一:引用必须初始化,指针没有要求
int a = 10;
int& b = a; //b需要指明是哪个变量的别名
int* a; //指针不作要求
引用:代表起别名,需要指明是哪个变量的别名
指针:代表地址,可以在需要使用的时候再赋予空间地址
(2)区别二:引用很专一,指针很花心
int main(){
int a = 10,c = 20;
int& b = a;
int* p = &a; //p指向a
p = c //p指向c
}
引用 ======》 绑定一个实体以后,不能再绑定其他实体;
指针 ======》 可以随时改变地址以及地址指向的内容
3、使用的角度
(1)区别三:指针需要显式解引用,引用编译器自己处理
int Test1(int* p)
{
*p = 10; //解引用才能使用
}
int Test2(int& p)
{
p = 10; //可以直接使用
}
(2)区别四:引用比指针使用起来相对安全
(3)区别五:使用引用无需开辟空间,但是指针需要通过开空间,被赋予空间地址
int main(){
int a = 10;
int& b = a;
b = 20; //修改实体a的值
int* p; //一开始可以无需初始化
p = new int[1]; //分配 10个int类型的空间
*p = 20;
}
五、验证引用的底层是指针实现的
我们以交换两个变量的值为例,一个使用引用实现,一个使用指针实现
我们通过反汇编来验证
int main(){
int a = 10;
int& b = a; //b绑定实体a
int* p = &a; //p获取a的地址,指向a的空间
return 0;
}
lea:表示取地址,取 a 的地址放入寄存器eax
mov:表示赋值,把eax的地址赋值给 b
由此可见,引用的底层依然是地址的传递
六、引用的数据类型转换
(1) 普通数据类型转换
有的时候我们会遇到下面这种情况
int main(){
double d = 3.14;
int i = d; //小数部分被舍弃,把整数部分赋值给i
}
从double ==> int,数据类型转换的时候,发生了数据截短,d 的小数部分被舍弃了,d 的整数部分赋值给 i
这个过程中发生了什么??
===》
d 把整数部分取出来,赋值给一个临时变量,然后再把这个临时变量赋值给 i
(2) 引用的数据类型转换
int main(){
double d = 3.14;
int& i = d; //小数部分被舍弃,把整数部分赋值给i
}
单纯的添加一个& ,程序会报错
注意!!!
这里 i 绑定的实体不是 d,而是临时变量!!
临时变量是const类型的,但是 引用(别名)的类型是 int,权限扩大,所以会报错
解决方法是 把引用类型也变成 const类型
int main(){
double d = 3.14;
const int& i = d; //小数部分被舍弃,把整数部分赋值给i
}