- 如果函数要使用参数,则必须声明接受参数值的变量。这些变量称为函数的形式参数。形式参数就像函数内的其他局部变量,在进入函数时被创建,退出函数时被销毁。默认情况下,C++使用传值调用来传递参数。一般来说,这意味着被调用函数内的代码不能改变用于调用函数的实际参数。当调用函数时,有三种向被调用函数传递参数的方式:
- 5.1 传值调用
- 传值调用:形参是实参的拷贝,改变形参的值并不会影响外部实参的值。从被调用函数的角度来说,值传递是单向的(实参->形参),参数的值只能传入,不能传出。当函数内部需要修改参数,并且不希望这个改变影响调用者时,采用值传递。把实际参数的实际值复制一份再传给被调用函数的形式参数。在这种情况下,修改被调用函数内的形式参数不会影响实际参数。默认情况下,C++使用传值调用方法来传递参数。一般来说,这意味着被调用函数内的代码不会改变用于调用函数的实际参数。函数 swap() 定义如下:
// 传值调用方式
void swap(int a, int b){
int temp;
temp = a;
a = b;
b = temp;
}
// 1 传值调用
int a = 4, b = 40;
cout << "交换前的a, b值: " << "a = " << a << ",b = " << b << endl;
swap(a, b); // 传值调用只是形参从实参那复制了一份实参的值,被调用函数内的代码不会改变用于调用函数的实际参数
cout << "交换后的a, b值: " << "a = " << a << ",b = " << b << endl;
- 5.2 指针调用
- 指针调用:形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进行的操作。把实际参数的地址复制给被调用函数中的形式参数。在被调用函数中,从实际参数那复制过来的地址可以用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。
- 按指针传递值,参数指针被传递给函数,就像传值给函数一样。因此相应地,在下面的函数swap1()中,需要声明函数形式参数为指针类型,该被调用函数用于交换参数所指向的两个整数变量的值。
// 指针传递方式
void swap1(int *a, int *b){
int temp;
temp = *a;
*a = *b;
*b = temp;
}
// 2 指针调用
int x = 4, y = 40;
cout << "交换前的x, y值: " << "x = " << x << ",y = " << y << endl;
swap1(&x, &y); // 实际参数将实际值的地址复制后再传给形式参数,形式参数获得地址后,在被调用函数的内部可以通过传进来的地址访问调用中用到的实际参数,修改形式参数会影响实际参数!
cout << "交换后的x, y值: " << "x = " << x << ",y = " << y << endl;
- 5.3 引用调用
- 引用调用: 形参相当于是实参的"别名",对形参的操作其实就是对实参的操作,在引用传递过程中,被调函数的形式参数虽然也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。把实际参数的引用的地址复制给形式参数。在被调用函数内,该引用用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。
- 按引用传递值,即实际参数的引用被传递给被调用函数,就像传递其他值给被调用函数一样。因此,在下面的函数swap2()中,需要声明函数参数为引用类型,该函数用于交换参数所指向的两个整数变量的值。
// 引用传递方式
void swap2(int &a, int &b){
int temp;
temp = a;
a = b;
b = temp;
}
// 3 引用调用
int m = 4, n = 40;
cout << "交换前的m, n值: " << "m = " << m << ",n = " << n << endl;
swap2(m, n); // 将实参的引用的地址复制了一份传给形参,形式参数获得实际参数引用的地址后,在被调用函数的内部可以通过传进来的实际参数的引用的地址访问调用中用到的实际参数,修改形式参数会影响实际参数!
cout << "交换后的m, n值: " << "m = " << m << ",n = " << n << endl;