1.引用传递参数
传递引用给函数与传递指针的效果一样,传递的是原来的变量或对象,而不是在函数作用域内建立变量或对象的副本。
在8.6节中,我们看到对swap(int,int)传值方式函数的调用不影响调用函数中的实参,结果并未达到交换数据的预想目的。
使用指针传递方式的swap(int *,int *)函数的调用,能够达到预定的目的(见8.6 节),但是函数的语法相对传值方式来说比较累赘。首先,在swap()函数内需要重复递引用(dereference)(*px),这容易产生错误且难于阅读。其次,调用函数需要传递变量地址,使swap()内部的工作对用户太过显然。而且还有swap(&x,&y)的形式会造成一种交换两个变量地址的错觉。
C++的目标之一就是让使用函数的用户无须考虑函数是如何工作的。传递指针给使用函数的用户增加了编程和理解的负担,这些负担本应属于被调用函数。
例如,下面的程序用引用改写swap()函数的定义及调用:
//*********************
//** ch9_4.cpp **
//*********************
#include <iostream.h>
void swap(int &x,int &y);
void main()
{
int x=5, y=6;
cout <<"before swap, x:" <<x <<" ,y:" <<y <<endl;
swap(x,y);
cout <<"after swap, x:" <<x <<" ,y:" <<y <<endl;
}
void swap(int &rx,int &ry)
{
int temp=rx; rx=ry; ry=temp;
}
运行结果为:
before swap,X:5,y:6
after swap,x:6,y:5
在主函数中,调用swap()函数的参数是x和y,简单地传递变量而不是它们的地址。而事实上,传递的是它们的地址。引用传递的内存布局与指针相仿,只是操作完全不同。每当使用引用时, C++就去求该引用所含地址中的变量值,见图9-4:
引用具有指针的威力,但是调用引用传递的函数时,可读性却比指针传递好。引用具有传值方式函数调用语法的简单性与可读性,但是威力却比传值方式强。
尽管引用可以表达清晰并让程序员负责了解如何传递参数,但是在有些情况下它们能隐藏错误。
例如,下面的代码在没有看到函数原型之前可能会误认为实参a和b是通过值来传递的,从而不能通过函数调用来修改它,而事实上却能够修改:
int a=10;
int b=20;
swap(a,b);
因为引用隐藏了函数所使用的参数传递的类型,所以无法从所看到的函数调用判断其是值传递还是引用传递。正因为此,下面的代码中两个重载函数将引起编译报错:
void fn(int s)
{
//...
}
void fn(int&t)
{
//...
}
void main()
{
int a=5;
fn(a); //error匹配哪一个函数?
}