1.简介:引用(reference)有时候又称为别名(alias),他可以用作对象的另一个名字。通过引用我们可以间接地操纵对象,使用方式类似于指针。但是不需要指针的语法。在实际的程序中,引用主要被用作函数的形式参数----通常将类对象传递给一个参数。
2.引用必须被初始化:int &refVal;//错误 int ival=1024; int&refVal=ival;//这是对的,refVal是一个指向int对象ival的引用。
3.虽然引用也可以被用作一种指针,但是像对指针那样用一个对象的地址初始化引用是错误的。然而,我们可以定义一个指针引用,例如:
int ival=1024;
int &refVal=&ival;//错误:refVal是int类型,不是int*
int*pi=&ival;
int*&ptrVal2=pi;//可以这样理解,ptrVal是一个指向指针(pi)的引用
3.一旦引用已经定义,它就不能再指向其他的对象(这也是为什么必须要被初始化的原因)。下面代码:
int ival=1024;
int &refVal=ival;
int min_val=0;
reVal=min_val;
该操作并不会使refVal指向min_val,而是会使refVal指向的对象ival的值被改变为min_val的值。就相当于:ival=min_val;
4.引用的所有操作实际上都被应用在它所指的对象的身上,包括取地址操作符,如:
refVal+=2;它相当于ival+=2;
类似的 int ii=refVal;相当于int ii=ival;
类似的,int *pi=&refVal;相当于int *pi=&ival;
5.说说const引用的一些特殊功能
const引用可以用不同类型的对象初始化(只要能从一种类型转换到另一种类型即可),也可以是不可寻址的值来初始化,比如蚊子常量。如下:
double dval=3.14159;
const int &ir=1024;//用文字常量来初始化
const int &ir2=dval;//用double类型来初始化指向int型的引用
const double &dr=dval+1.0;//还可以这样
注意这些初始化的方法只适用于const引用。对于非const引用,这些初始化的方法是不合法的。为什么呢?
原因要从引用的运作机制说起:引用在内部存放的是一个对象的地址,它就是该对象的别名。对于不可寻址的值,比如文字常量,以及不同类型的对象,编译器为了实现引用,必须生产一个临时对象,引用实际上指向该对象,但用户不能访问它。如:当我们写:
double dval=1024;
const int &ri=dval;的时候,
编译器其实是这样做的:
int temp=dval;
const int &ri=temp;
如果我们给ri赋一个新的值,则这样做不会改变dval,而是改变了temp。对用户来说,就好像修改动作没有生效(这并不是好事)。所以最好的手段就是使他无法修改,定义为const引用,表示该引用指向的对象为const,无法修改,自然也就不会出现这个问题了。
6.最后来说说指针和引用的最大区别:引用必须总是指向一个对象。(必须初始化,而且初始化以后,就相当于它跟这个对象绑定了),当我们用一个引用去给另一个引用赋值,改变的是被引用的对象本身,而不是引用。
如:
int*pi=0;//这时候我们的意思是指针pi不指向任何对象。
而const int &pi=0;则相当于:int temp=0;const int &ri=temp;
又比如:
int ival=1024,ival=2048;
int *pi=&ival,*pi2=&ival2;
pi=pi2;
这将导致
pi和pi2的值相同,她们都指向ival2.而ival并没有改变。
但是假如:
int &ri=ival,&ri2=ival2;
ri=ri2;
则相当于ival=ival2.但是ri和ri2还是指向原来各自指向的对象。
这就是二者最大的区别。
7.开始的时候说了,引用对象主要被用作函数的形式参数。现在来说说它的工作机制:
bool get_next_value(int &next_value);//这是个函数,它的形参是一个引用。
当我们调用这个函数时:
int ival;
while(get_next_value(ival))……。
其实发生了这样的事情:
int &next_value=ival;
8.没有指向引用的指针,那样是不合法的,也就是说,没有这种形式int &*p.