1.1 参数的传递方式
(1)传值
传值是将实参的副本传递(复制)给被调用函数的形参
例1 给出成绩的评语
#include<iostream>
using namespace std;
void grade(char ch);
int main()
{
char a1 = 'b',a2='c',a3='f';
grade(a1);
grade(a2);
grade(a3);
return 0;
}
void grade(char ch)
{
switch (ch)
{
case 'A':
case'a':
cout << "优秀" << endl;
break;
case 'B':
case'b':
cout << "好的" << endl;
break;
case 'C':
case'c':
cout << "及格" << endl;
break;
default:
cout << "不及格" << endl;
}
}
在上面程序中,函数参数传递方式采用的就是复制方式。
由于传值方式是将实参的值复制到新惨重,因此实参和形参是两个不同的变量,有各自的存储空间,函数形参可以看作是函数的局部变量。传值的最大好处是函数调用不会改变调用函数实参变量的内容,可以避免不必要的副作用。
(2)传地址
有时确实需要通过函数调用来改变实参变量的值,或通过函数调用返回多个值(return语句只能返回一个值),这时依靠传值的方式是不能达到目的的。
通过下面的例子来看通过传值的方式能不能交换两个变量的值。
例2 试图按传值方式换变量值
#include<iostream>
using namespace std;
void swap(int x, int y);
int main()
{
int a = 2, b = 3;
swap(a, b);
cout << a << " " << b << endl;
return 0;
}
void swap(int x, int y)
{
int temp;
temp = x;
x = y;
y = temp;
}
从运行结果中发现变量a和变量b没有交换,原因在于swap函数的参数传递采用了传值方式,函数调用仅仅将实参变量a和b的值复制给了形参变量x和y,因此调用swap(a,b)时仅仅交换了两个形参变量x和y的值,而相应实参变量没有交换。
例3 传指针方式交换变量值。
#include<iostream>
using namespace std;
void swap(int* x, int* y);
int main()
{
int a = 2, b = 3;
swap(&a, &b);
cout << a << " " << b << endl;
return 0;
}
void swap(int* x, int* y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
上面程序运行结果显示变量a和b的值确实交换了,这是由于swap函数参数传递的不是变量的值,而是变量的地址。因此形参变量x和y存放的是变量a和b的地址,也就是说变量x和y分别指向变量a和b。在swap中交换的是指针变量x和y所指向的内容,因此变量a和b的值被交换。
传指针属于显示传递地址。尽管传递指针可以达到目的,但传递方式略显笨拙,而且也不直观。首先实参变量需要用取地址运算符&来传递变量地址;其次形参实际上是实参指针的一个副本,在swap()函数内还需要通过指针运算,如*p=*x等间接取、间接存来交换变量,不仅难以理解,还容易产生错误
C++提供了一种引用机制,他的本质任然是地址。通过引用传递函数参数属于隐式传地址,当参数声明为引用,在函数调用时,编译器会自动将实参的地址传给被调用函数。
例4 传引用方式交换变量
#include<iostream>
using namespace std;
void swap(int& x, int& y);
int main()
{
int a = 2, b = 3;
swap(a, b);
cout << a << " " << b << endl;
return 0;
}
void swap(int& x, int& y)
{
int temp;
temp = x;
x = y;
y = temp;
}
在上面程序中。函数swap的形参说明成引用,引用实际上是另一个变量的别名。与一般的引用不同(一般是定义时初始化为另一个变量的引用),引用参数是在函数被调用时初始化为实参变量的引用。
注:函数引用参数仅在函数定义时说明,而带引用参数的函数的调用形式与值参数相同。
在C++中,当函数参数需要传递指针时,建议使用引用来代替指针(指针方式属于C语言风格),因为引用比指针更直观。
在下面三种情况中,引用参数十分有用:
(1)要从函数中返回多个值。
(2)通过函数调用要改动实参值。
(3)传递地址可以节省复制大量数据所需的内存空间和时间。
前两种情况已经说明,下面对第三种情况进行简述说明。
当函数作为大数据类型(如后面将介绍的类类型),而着类对象通常包含多个数据,当它们作为值参数传递时,实参对象复制给形参变量(对象中的每个数据都要分别复制到形参中)将要占用许多空间并要消耗时间。因此,好的程序设计实践通常将大数据类型参数作为引用参数,这样将节约参数传递时间和空间。
但是也要注意使用引用(或指针)所带来的副作用。我们知道,传值调用的最大好处是函数调用不会改变实参变量的内容,而使用引用(或指针)可能会由于疏忽而导致不该修改的实参变量在函数调用时被修改。
保护实参不被修改的办法是使用const引用函数,具体做法是使用关键字const来修饰引用参数。
例5 const引用参数
#include<iostream>
using namespace std;
int a(const int& val);
int main()
{
int v = 10;
cout << v << " " << a(v) << endl;
return 0;
}
int a(const int& val)
{
return -val;
}
将val声明为常量引用参数后,函数不能对val值作任何修改。如果a()函数改写为一下编译器就会报错。
int a(const int& val)
{
val -= 1;
return val;
}
1.2 默认参数
在C++中可以为形参指定默认值,在函数调用时没有指定与形参相对应的实参时就自动使用默认值。默认参数可以简化复杂函数调用。
默认参数通常在函数名第一次出现在程序中的时候指定,如在函数原型中指定默认参数值。指定默认参数的方式从语法上看与变量初始化相似。
例6 默认参数的用法
#include<iostream>
using namespace std;
void a(int x = 0, int y = 1);
int main()
{
a(2, 3);
a(2);
a();
return 0;
}
void a(int x, int y)
{
cout << x << " " << y << endl;
}
参考《全国计算机等级考试二级教程——C++语言程序设计》