所以,总结:
1.出了函数作用域,返回变量不存在了,不能用引用作返回值,因为引用返回的结果是未定义的
2.出了函数作用域,变量还在,可以用引用。
3.正确使用用引用做返回值,可以减少拷贝,提高效率;还可以修改返回值。
返回数组中的值,是偶数的数,一律乘二,很方便的修改了返回值!
2.做参数
作为普通参数:
请看本文章刚开头,引用做参数的好处!
那么我们会发现,交换两个数时,我们需要将变量地址传过去,创建指针变量拷贝变量地址。
但若用引用做参数,就不需要拷贝,直接就可以修改,别名也就是自己本身嘛!
好处是:减少拷贝,提高效率!
作为输出型参数:
int& func(int m,int&p) { p=p+m; return p; } int main() { int a=10; int b=20; func(a,b); cout<<a<<endl; return 0; }
int& p作为输出型参数,使用引用作为参数时,无需拷贝,还可以直接改变形参,进而改变实参。
3.const修饰的引用
先看下面的一段代码,从中体会const修饰引用注意要点:
指针和引用赋值中,权限可以缩小,但是不能放大
int main() { // 指针和引用赋值中,权限可以缩小,但是不能放大 int a = 0; //可读可写 // 权限平移 ,权限没有改变 int& ra = a; //可读可写 const int b = 1; //可读不可写 a = b; // 拷贝 读取b的值给了a,可以 int& rb = b; // 我引用你,此时 int& rb 就是可读可写,将权限放大 不行 const int& rra = a; // 我引用你,我的权限的缩小 可以 //rra++; a++; const int& rb = b; // 权限平移,可以 }
所以在我们使用引用作为函数参数时,一般都要加const修饰,防止权限被放大。
比如:const int&......
有人会想,那既然const了,那就改变不了变量了。
但既然有防止权限被放大,那么定义变量时,他的权限就是小权限,根本不需要将其改变。
4.常量的引用
1.类型转化时
doubule b=9.88;
int a=(int)b; //可以
int a=b; //可以
int& rb=b; //不可以
在发生类型转化时,不管 强制类型转化 还是 隐式类型转化,都会产生临时变量,而非改变变量本身。
double d = 9.88;
cout << (int)d << endl;
此时,d被强转为int,但并没有改变d本身的值,是在类型转化
的时候,会创建临时变量,然后把临时变量的值拷贝到了i中。
int i = (int)d; // 可以
//int& ri = d; // 不可以,因为在类型转化时,是借助中间的临时变量,int&ri是在给中间的临时变量取别名,就会把临时变量的权限的扩大,所以不可行!!
const int& ri = d; // 可以,平移权限
注意:临时变量具有常性,不可以被修改!!
2.返回函数时:
int Count() { int n = 0; n++; ... return n; } int main() { int& ret = Count(); //权限增大 const int& ret = Count(); //权限平移,可以 }
临时变量具有常性
当返回函数时,临时变量会存在上一个调用它的函数栈帧中,用引用来接收,会扩大临时变量的权限,所以只有在const 引用时,才可以使用!
三.引用和指针的区别
在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。
在底层实现上实际是有空间的,因为引用是按照指针方式来实现的,都是先通过传地址,解引用来改变实体内容的。
引用和指针的不同点:
1. 引用概念上定义一个变量的别名,指针存储一个变量地址。
2. 引用 在定义时 必须初始化 ,指针没有要求
3. 引用 在初始化时引用一个实体后,就 不能再引用其他实体 ,而指针可以在任何时候指向任何
一个同类型实体
4. 没有 NULL 引用 ,但有 NULL 指针
5. 在 sizeof 中含义不同 : 引用 结果为 引用类型的大小 ,但 指针 始终是 地址空间所占字节个数 (32
位平台下占 4 个字节 )
6. 引用自加即引用的实体增加 1 ,指针自加即指针向后偏移一个类型的大小
7. 有多级指针,但是没有多级引用
8. 访问实体方式不同, 指针需要显式解引用,引用编译器自己处理
9. 引用比指针使用起来相对更安全
总结
引用这一节中,有太多的细节值得我们去反复思考琢磨了,有一个个很细的知识点相互联系的,所以我们要踏踏实实的学习,并反复去复习!!
有几点: