引用(reference)
函数间传送变量的值的时候,传送的是一个变量的副本,这个副本与原来的变量值相同,但是地址不同,所以不是原来的变量。比如定义变量
int x;
f(x);
f(x)中调用时,使用的是值等于x的另一个变量x′。
定义引用
int rats = 101;
int & rodents = rats;
rodents和rats一模一样,同样的地址,同样的值,修改rodents就同时修改了rats,修改rats也修改了rodents。
int & rodents=rats 相当于 const int * rodents = &rats,所以必须在初始化的时候指定引用的对象。
int rat;
int & rodent;
rodent = rat; // No, you can’t do this.
引用的函数调用
引用在函数调用的时候传送的是原来的变量,原变量的地址,原变量的值,如果在调用的函数中进行修改,会修改原来的变量值。
void swapr(int & a, int & b); // function defines
……
int wallet1 = 300;
int wallet2 = 350;
swapr(wallet1, wallet2);
传递的不再是副本,是变量本身。
特别的:
free_throws & accumulate(free_throws & target, const free_throws & source)
{
……;
return target;
}
free_throws temp;
free_throws a, b;
accumulate(a, b) = temp;
由于引用传递的时变量本身,所以返回值是引用时,返回的也是变量本身,即返回target,在函数调用中为a,即返回a。accumulate(a, b)=temp;操作的结果是:a,b的值先在accumulate()中被处理一遍之后,返回的a被赋值为temp。
因此下面的函数避免使用:
const free_throws & clone2(free_throws & ft)
{
free_throws newguy;
newguy = ft;
return newguy;
}
由于引用是对变量进行直接操作,而不是对变量的副本操作,在函数clone2()结束时,变量newguy已经被释放,返回的值虽然有确定地址(newguy的地址),但是没有确定的值(不是ft, ft的地址不是newguy的地址)。
可以用下面返回方式:
const free_throws & clone(free_throws & ft)
{
free_throws * pt;
*pt = ft; // copy info
return *pt; // return reference to copy
}
这里pt指向ft,ft是在内存空间存在固定地址的,所以返回的时ft的地址。
引用的优点
1,修改传递的参数值;
2,对长结构体等对象直接传递原来的结构体,不需要重新复制副本。
函数调用不需要修改的变量时
1,如果数据对象很小(基本数据类型),直接传值;
2,如果数据对象是个数组,只能使用指针,并且加const;
3,如果数据对象是很大的结构体,使用指针或者引用,并且加const;
4,如果数据对象是类对象,使用引用,并且加const。
函数调用需要修改的变量时
1,如果数据对象是基本数据类型(built-in),使用指针,以表明数据需要修改;
2,如果数据对象是数组,使用指针;
3,如果数据对象是结构体,使用引用或者指针;
4,如果数据对象是类对象,使用引用。