当前位置: 首页 > 文档资料 > C++大学教程 >

5.4 按引用调用函数

优质
小牛编辑
142浏览
2023-12-01

C++ 用三种方式向函数传递数值:按值调用(call-by-value)、用引用参数按引用调用(call-by-reference reference argument)和用指针参数按引用调用(call-by-reference pointer argument)。第3章比较了按引用调用与按值调用,本章主要介绍用指针参数按引用调用。

第3章曾介绍过,return 可以从被调用函数向调用者返回一个值(或不返回值而从被调用函数返回控制)。我们还介绍了用引用参数将参数传递给函数,使函数可以修改参数的原有值(这样可以从函数 返回 多个值),或将大的数据对象传递给函数而避免按值调用传递对象的开销(即复制对象所需的开销)。指针和引用一样,也可以修改调用者的一个或几个变量,或将大的数据对象指针传递给函数而避免按值调用传递对象的开销。

在 C++ 中,程序员可以用指针和间接运算符模拟按引用调用(就像C语言程序中的按引用调用一样)。调用函数并要修改参数时,传递该参数地址,通常在要修改数值的变量名前面加上地址运算符(&)。第4章曾介绍过,数组不能用地址运算符(&)传递,因为数组名是内存中数组的开始位置(数组名等同于 &arrayName[0] ),即数组名已经是个指针。向函数传递参数地址时,可以在函数中使用间接运算符形成变量名的同义词、别名或浑名,并可用其修改调用者内存中该地址的值(如果变量不用 const 声明)。

图 5.6 和 5.7 的程序是计算整数立方函数的两个版本 cubeByValue 和 cubeByReference。图 5.6 按值调用将变量 number 传递给函数 cubeByValue。函数 cubeByValue 求出参数的立方,并将新值用return语句返回main,井在 main 中将新值赋给 number。可以先检查函数调用的结果再修改变量值。例如,在这个程序中,可以将 cubeByValue 的结果存放在另一变量中,检查其数值,然后再将新值赋给 number。

1 // Fig. 5,6: fig0506,cpp
2 // Cube a variable using call-by-value
3 #include <iostream.h>
4
5 int cubeByValue( int ); // prototype
6
7 int main()
8 {
9 int number = 5;
10
11 cout << "The original value of number is "<< number;
12 number = cubeByValue( number );
13 cout << "\nThe new value of number is" << number << endl;
14 return 0;
15 }
16
17 int cubeByValue( int n )
{
18
19 return n * n * n; // cube local variable n
2O }

输出结果:

The original value of number is 5
The new value of number is 125

图 5.6 按值调用求出参数的立方

图 5.7 的程序按引用调用传递变量 nunber(传递 number 的地址)到函数 cubeByReference。函数 cubeByReference 取 nPtr(int 的指针)作为参数。函数复引用指针并求出nPtr所指值的立方,从而改变 main 中的 number 值。图 5.8 和 5.9 分别分析了图 5.6 和 1.7 所示程序。

1 // Fig. 5.7: fig05_07.cpp
2 // Cube a variable using call-by-reference
3 // with a pointer argument
4 #include <iostream.h>
5
6 void cubeByReference( int* ); // prototype
7
8 int main()
9 {
10 int number = 5;
11
12 cout << "The original value of number is "<< number;
13 cubeByReference( &number );
14 cout << "\nThe new value of number is "<< number << endl;
15 return O;
16 }
17
18 void cubeByReference( int *nPtr )
19 {
20 *nPtr = *nPtr = *nptr * *nptr; // cube number in main
21 }

输出结果:

The original value of number is 5
The new value of number is 125

图 5.7 用指针参数按引用调用求出参数的立方

常见编程错误 5.5
要复引用指针以取得指针所指的值时不复引用指针是个错误。

接收地址参数的函数要定义接收地址的指针参数。例如 cubeByReference 的函数首部如下所示:

void cubeByReference(int *nPtr)

这个函数首部指定函数 cubeByReferenee 接收整型变量的地址(即整型指针)作为参数,在nPtr中局部存放地址,不返回值。

cubeByReference 的函数原型包含括号中的 int* 。和其他变量类型一样,不需要在函数原型中包括指针名。参数名仅用于程序中的说明,编译器将其忽略。

在需要单下标数组参数的函数首部和函数原型中,可以用 cubeByReference 参数表中的指针符号。编译器并不区分接收指针的函数和接收单下标数组的函数。当然,函数必须“知道”何时接收数组或要进行按引用调用的单个变量。编译器遇到形如 int b[] 的单下标数组函数参数时,编译器将参数变为指针符号 int* const b (b 是指向整数的常量指针),const 见第 5.1 节介绍。声明函数参数为单下标数组的两种形式可以互换。

编程技巧 5.2

除非调用者显式要求被调用函数修改调用者环境中参数变量的值,否则按值调用将参数传递给函数。这是最低权限原则的另一个例子。

图 5.8 典型的按值调用分析

图 5.9 典型的用指针参数按引用调用分析