每次调用函数时都会重新创建该函数所有形参的值,此时所传递的实参将会初始化对应的形参。形参的初始化和变量的初始化一样,如果形参具有非引用类型,则复制实参的值,如果形参为引用类型,则它只是实参的别名。
1、非引用形参
普通的非引用类型的参数通过复制对应的实参实现初始化。当用实参副本初始化形参时,函数并没有访问调用所传递的实参本身,因此不会修改实参本身。
典型的例子:
int gcd(int v1,int v2) { while(v2) { int temp=v2; v2=v1%v2; v1=temp; } return v1; }
while循环体虽然修改了v1与v2的值,但是这些变化仅限于局部参数,而对调用gcd函数使用的实参没有任何影响。
总结:非引用形参表示对应实参的局部副本。对这类形参的改变仅仅改变的是局部副本的值。
(a)指针形参
函数的形参可以使指针,此时将复制实参指针。该类形参的任何改变也仅仅作用于局部副本,如果函数将新指针值赋值给形参,主调函数使用的实参指针的值将没有任何改变。
如何函数形参时非const类型的指针,则函数可以通过指针实现赋值,修改指针所指向对象的值。
例如:
void reset(int *p) { *ip=0; ip=0; }
调用该函数后,ip中所存的地址不变,地址中存放的值变成了0。
如果需保护指针指向的值,则形参需定义为指向const对象的指针。
例如:
void use_ptr(const int *p)
指针形参时指向const类型或非const类型,将影响函数调用使用的实参。我们既可以用int *也可以用const int *类型的实参类型调用use_ptr函数,但是仅能将int *类型的实参传递给reset函数。
总结:指针的初始化规则,可以将指向const对象的指针初始化为指向非const对象,但是不能让指向非cosnt对象的指针指向const对象。
2、引用形参
这是我在写而二叉搜索树的删除算法的时候引出的问题,引用形参很方便的改变指针的值,非引用形参则不能改变传入实参的值。下面对引用形参做一个总结。
例如需要交换两个实参的值,我们需要将形参定义为引用类型:
void swap(int &v1,int &v2) { int tmp=v2; v2=v1; v1=tmp; }
引用形参直接关联到其所绑定的对象,而并非实参的副本。定义引用时,必须用与该引用绑定的对象初始化该引用。
下面在在我的程序中用到的引用形参的使用方法:
(a)传递指向指针的引用
这里给出一个小例子:
void ptrswap(int *&v1,int *&v2) { int *tmp=v2; v2=v1; v1=tmp; }
这样就可以实现交换指针的值。
如果定义为int *v1,int *v2则交换的只是局部副本的指针的值,实参指针的值不受影响。