核心提示:在什么时候将函数的参数设为引用类型??当你在函数体里要改变参数的值时,就将函数参数类型声明为引用或者指针,这样函数体里对参数本身的操作才能生效。
最近在看程序结合实例,慢慢明白了引用类型的实际好处。
如:int beforeChange;
void ChangeValue(int valueBeforeChanged)
{
//change value
}
当把beforeChange传递给函数ChangeValue后,并没有将ChangeValue的实际值修改掉。因为在执行过程中只是将ChangeValue的副本传递给了函数,并没有将ChangeValue本身传递给函数。
如果要实现改变beforeChange值的目的,有两种方式:
第一种:为函数ChangeValue设函数返回值,返回值用来存放修改后的值,最后在函数体外将修改后的值赋给beforeChange。如下:
int beforeChange=5;
int ChangeValue(int valueBeforeChanged)
{
int valueAfterChanged;
//change value
return valueAfterChanged;
}
调用方式:beforeChange=ChangeValue(beforeChange);
第二种方法:将函数的参数设置为引用类型。如下:
int beforeChange;
void ChangeValue(int &valueBeforeChanged)
{
//change value
}
调用方式:ChangeValue(beforeChange);
在第二种方法中,只需要直接将beforeChange传递给函数就可以达到改变其值的目的。
用引用传递函数参数
1.引用类型
由类型的实际值引用(类似于指针)表示的数据类型。如果为某个变量分配一个引用类型,则该变量将引用(或“指向”)原始值。不创建任何副本。引用类型包括类、接口、委托和装箱值类型。
2.引用传递参数
传递引用给函数与传递指针的效果一样,传递的是原来的变量或对象,而不是在函数作用域内建立变量或对象的副本。
我们看到对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++就去求该引用所含地址中的变量值.
引用具有指针的威力,但是调用引用传递的函数时,可读性却比指针传递好。引用具有传值方式函数调用语法的简单性与可读性,但是威力却比传值方式强。
3.引用存在的问题
尽管引用可以表达清晰并让程序员负责了解如何传递参数,但是在有些情况下它们能隐藏错误。
例如,下面的代码在没有看到函数原型之前可能会误认为实参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匹配哪一个函数?
}