引用
引用的概念
引用并不是定义一个变量,而是给存在的变量取了一个别名。
语法上没有独立空间,和引用的实体共用一块空间。但其实在底层是有空间的,因为他是用指针的来实现的。
通过引用直接改变了值。
引用的注意事项
引用和引用的实体必须是同种类型。
b是引用。&b是别名
定义的时候必须初始化。
一个变量可以有多个引用。
一个引用一旦引用一个实体,不会改变。
(b,c,d的地址一直没有改变)
常引用
const修饰
不能修改的原因很简单,经过前面我们可以知道通过b可以修改a的值,a是const不被修改,b不带const就编译不通过了。(编译器检查的时候就会发现你不带const,是不是想修改a,b的权限放大是不被允许的)
那这样的,a是可以被修改,我让引用变量b不能
再来一个之前C语言学过的例子
int strlen(const char* a)
正因为这里的char被const修饰,所以外面传参可以传
char也可以传const char*
char* a;
const char* b;
strlen(a);
strlen(b);
假如
int strlen(char* a)
那么就只可以传char* 的变量了,传不了const char*
char* a;
const char* b;
strlen(a);
strlen(b);//不被允许的,你不能放大权限
引用也可以引用常量
const int& a=10;
这就容易理解多了,你得是const,不然我不让你修饰我,人家10本来就代表着10,你不带const你还想修饰我一个常数不成。
我们知道这样的代码,会进行隐式类型转换。
那么这样呢,编译不通过。
看起来的原因是dd为double类型不能用int& ri引用他。其实这种认识是错误的。
这样呢编译通过了,所以上述这种原因是不通过的。
我们来寻找他本质的原因,前面说过这里产生了隐式转换。
double dd=2.22;
int& ri=dd;
画图来了解一下它的流程:
实际的操作是dd把值给这个临时变量。
所以在这里引用的并不是dd,而是这个临时变量
临时变量隐式转换成int且具有常性,所以类型为const int,所以ri这个引用,它的类型 也为const int&;
引用的作用
引用做参数
以后会经常用到引用函数做参数。
1.引用做参数不需要拷贝。
a是x的别名
2.如果func中a不需要改变可以加const(缩小范围)。
①形参缩小了范围,在调用的时候实参可以传变量,也可以传常量,如果不加const,就只能传变量了。(可以看前面的常引用)
②如果存在隐式转换也可以传递。(形参不是const无法传递,因为传递的是中间的具有常性的临时变量)
C语言
Swap(&a,&b);
传地址外面才能拿到a,b的值
Swap(int* pa,int* pb)
{
int tmp=*pa;
*pa=*pb;
*pb=tmp;
}
C++
Swap(a,b);
做输出型参数改变值(同时C++兼容c,所以这里也构成了重载。)
//传参的时候引用才被定义
Swap(int& a,int& b)
{
int tmp=a;
a=b;
b=tmp;
}
传引用可以提高效率。
传引用可以减少深拷贝。
引用做返回值
做返回值也可以减少拷贝。(返回值,或者函数传参)
值做返回值
n拷贝给临时变量,临时变量拷贝给ret,两次
引用做返回值,一次拷贝
直接拷贝n
第一个代码去掉static没有问题,只是每次打印的值n为1。
第二个代码去掉static不行,因为加上staic他的生命周期变成全局,n可以给ret。去了static,n出了自己的作用域,销毁。临时变量是一个引用,所以它也销毁,怎么拷贝给ret
引用与指针的区别
这里只是大概的总结,我们要从用法,特点等角度来有条理地进行对比引用与指针。