》参数是函数间进行数据交换的主要方式。在C++中,函数之间传递参数有传值和传地址两种传递方式。此外,C++还提供默认参数机制,可以简化复杂函数的调用。
>传值
传值是将实参值的副本传递(拷贝)给被调用函数的形参。由于传值方式是将实参的值复制到形参中,因此实参和形参是两个不同的变量,有各自的存储空间,函数形参可以看做是函数的局部变量。
传值的最大好处是函数调用不会改变调用函数实参变量的内容,可避免不必要的副作用。
>传地址
有时确实需要通过函数调用来改变实参变量的值,或通过函数调用返回多个值(return语句只能返回一个值),这时仅靠传值方式是不能达到目的的。
#传指针方式交换变量值
#include<iostream>
using namespace std;
void swap(int*,int*);
int main(){
int a=2,b=5;
swap(&a,&b); //交换了实参的值!
cout<<a<<","<<b<<endl;
system("pause");
return 0;
}
void swap(int* px,int* py)
{
int temp;
temp=*px; //间接取
*px=*py; //间接取,间接存
*py=temp; //间接存
}
由于swap函数参数传递的不是变量的值,而是变量的地址。因此,形参变量px和py存放的是变量a和b的地址,也就是说变量px和py分别指向变量a和b。在swap中,交换的是指针变量px和py所指向的内容,因此,变量a和b的值被交换。
传指针属于显示的传递地址。尽管传递指针可以达到目的,但传递方式略显笨拙,而且也不直观。首先,实参变量需要用取地址运算符&来传递变量的地址;其次,形参实际上是实参指针的一个副本,在swap()函数内,还要通过指针运算,如*px=*py等间接取、间接存来交换变量值,不仅难于理解,还容易产生错误。
#引用传递函数参数
例:改写上面的程序
#include<iostream>
using namespace std;
void swap(int&,int&);
int main(){
int a=2,b=5;
swap(a,b); //在此,编译器自动将a,b的地址传递给swap函数
cout<<a<<","<<b<<endl;
system("pause");
return 0;
}
void swap(int& x,int& y)
{
int temp;
temp=x;
x=y;
y=temp;
}
通过引用传递函数参数属于隐式传地址,当参数声明为引用,在函数调用时,编译器会自动将实参的地址传给被调用函数。在上面的程序中,函数swap的形参说明成引用,引用实际上是另一个变量的别名。与一般的引用不同(一般是定义时初始化为另一个变量的引用),引用参数是在函数被调用时被初始化为实参变量的引用。
注:函数引用参数仅在函数定义时说明,而带引用参数的函数的调用形式与值参数相同。在C++中,当函数参数需要传递地址时,建议使用引用来代替指针(指针方式属于C语言风格),因为引用比指针更加直观。
>在这三种情形中,引用参数十分有用:
(1)要从函数中返回多个值。
(2)通过函数调用要改动实参值
(3)传递地址可以节省拷贝大量数据所需的内存空间和时间
注:当函数参数为大数据类型,而这类对象通常包含有多个数据,当它们作为值参数传递时,实参对象拷贝给形参变量(对象中的每个数据都要分别拷贝到形参中)将要占用许多空间并要消耗时间。因此,好的程序设计时间通常将大数据类型参数,如类类型参数,作为引用参数,这样将节省参数传递的时间和空间。
但是,也要注意使用引用(或指针)所带来的副作用。使用引用(或指针)可能会由于疏忽而导致不该修改的实参变量在函数调用时被修改。保护实参不被修改的办法是使用const引用参数,具体做法是使用关键字const来修饰引用参数。
>默认参数
在C++中,可以为形参指定默认值,在函数调用时没有指定与形参相对应的实参时就自动使用默认值。默认参数可以简化复杂函数的调用,使用默认参数,程序员只需记住针对确切情形有意义的参数,不需要指定常见情况下使用的参数。
默认函数通常在函数名第一次出现在程序中的时候指定,如在函数原型中指定默认参数值。指定默认参数的方式从语法上看与变量初始化相似。
例如: void myfunc(int x=0,int y=1);
如果一个函数中有多个参数,则默认参数应从右至左逐个定义。