首先,我想说为什么,要加入引用,c/c++函数默认都是按值传递,按值传递的原理就是在内存中另外开辟一块空间来拷贝原数据,那么这两块空间的地址是不一样的,被调用函数操纵的是另一块内存的数据,只是数据刚好相等罢了。这也就是为什么按值传递来实现数据的交换不可行,因为你压根操纵的知识一块副本数据!
按值传递要求一块内存空间来拷贝原数据,当数据量不大时,这无足轻重,当数据量很大,如过是结构体或者类对象的时候,这就很消耗内存空间。所以之前我们选择传递指针。那现在我们有了一个新的更直观的选择---引用。引用在我看来跟指针是一回事儿,引用在底层的实现其实就是一个const指针。
引用分为左值引用和右值引用;那什么是左值,什么是右值呢?
左值是是能在内存空间中寻址的数据,如变量,解除引用的指针等等,简单点说,就是你在代码中能使用取地址符&的,就是左值。例如:定义一个整形变量int a;你能对a取地址:&a 代码不会出现问题;
但是如果你代码中出现 :&10 又或者&(a+10);那么程序就会报错,因为10和后面那个表达式你找不到他们的地址,他们一般保存在寄存器中; 那后面不能使用取地址符的,就叫做右值,一般是常量,表达式等等;
有了左值右值的概念,我们再来谈谈左值引用和右值引用;
左值引用:故名思议,和左值绑定起来的引用,即赋值号左边一定要是一个左值才行;例如:
int b ; // b是左值 int & c = b ; //这是可行的
左值引用其实就是给原来的变量起了一个新的名字,这两个变量其实都表示同一个地址;如果上面例子中b在内存中的地址假设是0xAAAA;那么c在内存中的地址也是0xAAAA;
左值引用跟const的用法类似,必须在定义的时候就初始化(即和某个左值绑定在一起),以后都不能在更改,看看下面这个例子:
int a =10;
int &b =a //即将b和a绑定在一起
int c = 100;
b = c;
结果会如何呢? 分别打印abc,可以看到a=100,b=100,c=100;因为a与b一旦绑定,就可以看成是同一个变量,你把c的值赋值给b,其实就相当于赋值给a;
上述是非常量引用,即没有加上const的引用,如果我们在引用前面加上一个const会产生什么影响呢?在我看来 影响有两个
1)假如你定义了一个常量引用: int a; const int & b =a ;//此时b是常量引用;
那么你不能通过b来修改这个变量的值;(这个const 指针是一样的);
2)第二个影响,可能会产生一点歧义,让我细细道来:如果你加入了const ,那么你赋值号右边可以是常量 ,表达式这些右值! 可能有的同学就疑惑了,刚刚上面不还说左值引用赋值号右边不是一定要是左值嘛? 这个没错,但是加了const以后,情况发生了一点变化。
首先加了const代表不能通过这个引用来修改,那么c++为了提高通用性(例如函数传参的时候),会在内存空间中找一块地址,这块地址是可寻址的,来存放那个右值,然后引用再和这块地址来绑定起来,相当于说,最终绑定的还是左值,只是这个左值是编译器帮我创建的。举个例子:
const int & a = 10; //本来10是不可寻址的,但是加了const,编译器会在内存中创建一个临时变量来存放10;然后再将a和这个临时变量来绑定起来;
所以左值引用还是那个左值引用,并没有跟定义相违背哈!
说完了定义,我们再来说说引用的使用场景:
第一个就是作为函数参数来传递;如果我们在函数形参中使用了引用,那在函数调用的时候会完成引用的定义和初始化,这样实参和形参将会指向同一个地址,而不需要拷贝,大大的减少了内存的消耗;而且能实现对原数据的修改,达到指针的效果,但是引用比指针更加直观;
第二个就是作为函数的返回值;
常规返回值的流程是现在内存中找一个临时的地方来存放函数返回的值,然后再将这个临时地址的值复制给变量;
但是引入引用后,就跳过了中间找一块临时内存的这一步,函数直接将引用指向的值复制给变量,大大提高了函数的速度;
但是引用作为函数的返回值,要注意一点:不能返回局部变量的引用:例如:
int & get_sum(int &a,int &b) //这个函数传递两个引用进来,然后定义一个局部变量c等于a 和b的和,然后返回c的引用;这样看似可行,但是c是局部 变量,get_sum函数结束后,将释放c的内存,那c的 引用将会绑定一块无效的地址,这样显然是不行的
{ int c;
c=a+b;
return c;
}
如何防止避免这样的错误呢?第一个,我们可以返回调用函数传进来的引用:如 代码修改为:
a = a+b; return a; 这样是可行的,因为,a,b本来就是调用函数传进来的引用,被调用函数消亡后也不会消亡;第二个那就是定义全局变量了,如加上static关键字或者使用new;
以上就是我对左值引用的理解啊;刚学习,如有不足的地方请多多包涵!欢迎交流!一起进步!
如过觉得可以就点个攒吧!