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

4.5 将数组传递给函数

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

要将数组参数传递给函数,需指定不带方括号的数组名。例如,如果数组hourlyTemperatures声明如下:

int hourlyTemperatures[24];

则下列函数调用语句:

modifyArray(hourlyTemperatutes,24);

将数组 hourlyTemperatures 及其长度传递给函数 modifyArray。将数组传递给函数时,通常也将其长度传递给函数,使函数能处理数组中特定的元素个数(否则要在被调用函数中建立这些信息,甚至要把数组长度放在全局变量中)。第8章介绍Array类时,将把数组长度设计在用户自定义类型中,每个Array对象生成时都“知道”自己的长度。这样,将Array对象传递给函数时,就不用把数组长度作为参数一起传递。

C++使用模拟的按引用调用,自动将数组传递绐函数,被调用函数可以修改调用者原数组中的元素值。数组名的值为数组中第一个元素的地址。由于传递数组的开始地址,因此被调用函数知道数组的准确存放位置。因此,被调用函数在函数体中修改数组元素时.实际上是修改原内存地址中的数组元素。

性能提示 4.4
模拟按引用调用传递数组时才能有性能上的意义。如果数组按值传递,则是传递每个元素的副本。对于经常传递的大数组,这是很费时间的,而且存放数组副本要占用很大空间。

软件工程视点 4.2
也可以按值传递数组(用第6章介绍的简单方法),但很少使用。

尽管模拟按引用调用传递整个数组,但各个数组元素和简单变量一样是按值传递。这种简单的单个数据称为标量(scalar 或scalar quanity)。要将数组元素传递给函数,用数组元素的下标名作为函数调用中的参数。第5章将介绍标量(即各个变量和数组元素)的模拟按引用调用。

要让函数通过函数调用接收数组,函数的参数表应指定接收数组。例如,函数modifyArray的函数苜部可能如下所示:

void modifyArray(int b[],int arraySize)

表示modifyArray要在参数b中接收整型数组并在参数arraySize中接收数组元素个数。数组方括号中的数组长度不是必需的,如果包括,则编译器将其忽略。由于模拟按引用调用传递数组,因此被调用函数使用数组名b时,实际上引用调用者的实际数组(上例中为数组hourlyTemperatures)。第5章介绍表示函数接收数组的其他符号,这些符号基于数组与指针之间的密切关系。
注意modlfyArray函数原型的表示方法:

void modifyArray(int[],int);

这个原型也可以改写成:

void modifyArray( int anyArrayName[],int( anyVariableName )

但第3章曾介绍过,C++编译器忽略函数原型中的变量名。

编程技巧 4.3

有些程序员在函数原型中包括变量名,使程序更清晰,编译器将忽略这个名称。

记住,函数原型告诉编译器参数个数和参数类型(按参数出现的顺序)。

图 4.14 的程序演示了传递整个数组与传递数组元素之间的差别。程序首先打印整型数组a的五个元素,然后将a及其长度传递给函数 modifyArray,其中将a数组中的元素乘以2,然后在main中重新打印 a。从输出可以看出,实际由modifyAnay修改a的元素。现在程序打印a[3]的值并将其传递给函数 modifyElement。函数 modifyElement 将参数乘以 2。然后打印新值。注意在main中重新打印a[3]时,它没有修改,因为各个数组元素是按值调用传递。

1 // Fig. 4.14: fig0414.cpp
// Passing arrays and individual array elements to functions
#include <iostream.h>
#include <iomanip.h>

void modifyArray( int [], int );  // appears strange
void modifyElement( int );

int main(){
  const int arraySize = 5;
  iht i, a[ arraySize ] = { 0, 1, 2, 3, 4 };

  cout << "Effects of passing entire array call-by-reference:"
  << "\n\nThe values of the original array are:\n";

  for( i=0;i< arraySize; i++ )
  cout(<< setw( 3 ) << a[ i ];

  cout << endl;

  // array a passed call-by-reference
  modifyArray( a, arraySize );

  cout << "The values of the modified array are:\n";

  for ( i = 0; i < arraySize; i++ )
  cout << setw( 3 ) << a[ i ] ;

  cout << "\n\n\n"
  << "Effects of passing array element call-by-value:"
  <<"\n\nThe value of a[3] is "<< a[3] <<'\n';

  modifyElement( a[ 3 ] );

  cout << "The value of a[ 3 ] is "<< a[ 3 ] << endl;

  return 0;
}

void modifyArray( int b[ ], int sizeofArray ){
  for ( int j = 0; j < sizeofArray; j++ )
  b[ j ] *= 2;
}

void modifyElement( int e ){
  cout << "Value in modifyElement is"
  <<(e *= 2 ) << endl;
}

输出结果:

Effects of passing entire array call-by-Value:

The values of the original array are:
     0 1 2 3 4
The values of the modified array are:
     0 2 4 6 8

Effects of passing array element call-by-value:

The value of a[3] is 6
Value in modifyElement is 12
The value of a[3] is 6

图 4.14  向函数传递数组和数组元素

有时程序中的函数不能修改数组元素。由于总是模拟按引用调用传递数组.因此数组中数值的修改很难控制。C++ 提供类型限定符 const,可以防止修改函数中的数组值。数组参数前面加上const限定符时,数组元素成为函数体中的常量,要在函数体中修改数组元素会造成语法错误。这样,程序员就可以纠正程序,使其不修改数组元素。

图 4.15 演示了 const 限定符。函数 tryToModifyArray 定义参数 const int b[],指定数组b为常量,不能修改。函数想修改数组元素会造成语法错误 Canot modify const object。const 限定符将在第7章再次介绍。

// Fig. 4.15: fig04_lS.cpp
// Demonstrating the const type qualifier
#include <iostream.h>

void tryToModifyArray( const int [] );

int main(){
  int a[] = {10,20,30};

  tryToModifyArray( a );
  cout << a[ 0 ] << ' ' << a[ 1 ] << ' ' << a[ 2 ] << '\n';
  return 0;
}

void tryToModifyArray( const int b[] ){
  b[ 0 ] /= 2;   // error
  b[ 1 ] /= 2;   // error
  b[ 2 ] /= 2;   // error
}

输出结果:

Compiling FIG04 15.CPP:
Error FIG04_iS.CPP 18: Canot modify a const object
Error FIG04_iS.CPP 19: Canot modify a const object
Error FIG04 15.CPP 20: Canot modify a const object
Warning FIG04_15,CPP 21: Parameter 'b' is never used

图 4.15  演示 const 限定符

常见编程错误 4.10
忘记数组按引用传递以至于修改数组可能造成逻辑错误。

软件工程视点 4.3
const 限定符可以用于函数定义中的数组参数,防止函数体中修改原数组,这是最低权限原则的另一个例子。函数不能提供修改数姐的功能,除非确实有必要。