在C++中提供了一个很简洁,并很有用的功能——引用
引用时别名:创建引用时,你将其初始化为另一个对象(即目标)的名称。然后,引用将成为目标的另一个名称,对引用执行任何操作实际上都是针对目标的.
实质上,引用的本质就是目标对象的一个别名。它与指针的不同是:定义指针还占四个字节,而引用不会开辟内存。并且引用在定义是必须给它赋值,即指定目标对象。并且不能再改变目标对象。
一、引用的创建和使用
int i;
int &ri=i;
此时 i就是ri,ri就是i。 注意:应用在定义的时候必须指定目标,即int &ri=i中的i,必须指定目标对象i.
二、引用参数
引用可传递参数,可实现与指针差不多的功能。
void swapint(int *a,int *b)
{
int temp;
temp=*a;
*a=*b;
*b=temp;
}这是C中利用指针实现的,调用这个函数的形式为:swapint(&x,&y);
void swapint(int &a,int &b)
{
int temp;
temp=a;
a=b;
b=temp;
}这是引用实现的,在调用此函数的形式为:swapint(x,y);c++自动把x,y的地址作为参数传递给swapint函数。
优点:有的时候,参数只是需要传值就可以解决,但是对象很大,传值的话编译器会进行对象(参数)的拷贝、构造、析构,这样浪费内存也浪费时间。此时就可以用引用(当然指针也是可以的),例如:
(类 Cat)
void swap(Cat &rp);//此处是函数声明 调用时的形式为:swap(redcat);
要是用指针的话就是 void swap(Cat *q); //此处是函数声明 调用时的形式为:swap(&redcat); /麻烦在于swap函数的定义时加入要表示对象的话,得用*q,但如果是引用的话,要是使用对象时,直接写rp即可。
在这儿,可能有人提出疑义,本来程序的需求是不改变这几个实参的值,但是现在子函数已经得到的是实参的地址,而不是得到的副本,要是在程序员不小心的情况下一旦修改了实参的值,这个方法岂不是不可取?
实际上这个问题很好解决,加上关键字const即可
引用:void swap(const Cat &rp);
指针:void swap(const Cat *q);或void swap(const Cat * const q)这样就可以达到安全、简洁、效率高的要求。
三、返回引用
如果一个函数返回了引用,那么该函数的调用也可以被赋值(结果可以再表达式的左边)。这里有一函数,它拥有两个引用参数并返回一个双精度数的引用:
double &max(double &d1,double &d2)
{
return d1>d2?d1:d2;
}
由于max()函数返回一个对双精度数的引用,那么我们就可以用max() 来对其中较大的双精度数加1:
max(x,y)+=1.0;
另外:在运算符重载上面用到了很多返回引用的功能,旨在尽可能的减少定义一些过渡对象(即尽可能的减少过渡对象的拷贝等操作)
如在一个重载运算符+ 的定义中用到了返回引用,例:
程序一:(返回引用)
Cat & Cat::operator+(const Cat &rCat) //C为Cat的成员变量
{
this->C+=rCat.C;
return *this ;
}此时返回应用,在进行这个函数调用的时候,一次过渡变量也没定义,也就不存在对象的拷贝。
程序二:(返回对象)
Cat Cat::operator+(const Cat &rCat) //C为Cat的成员变量
{
this->C+=rCat.C;
return *this ;
}此时返回的话,编译器就会自动定义一个对象去接受返回值,这样就会出现对象的拷贝
程序三:
Cat Cat::operator+(const Cat &rCat) //C为Cat的成员变量
{
Cat RedCat;
RedCat.C=rCat.C+this->C;
return RedCat;
}此时是直接定义了一个过渡变量,此时也存在一次的对象拷贝
这儿有一个疑惑:就是感觉程序二与程序三(都有一次对象的拷贝)有点冲突,还是对编译原理不了解,才会存在这样的疑惑,这个问题有待解决 ??????????????????????
四、常引用
常引用声明方式:const 类型标识符 &引用名=目标变量名;
用这种方式声明的引用,不能通过引用对目标变量的值进行修改,从而使引用的目标成为const,达到了引用的安全性。(在第二点中提及过)