1、C++中根本不存在所谓的“数组形参”,因为在数组传入时,实质上只传入指向其首元素的指针。
void average( int ary[12] ); //形参ary是一个int *
//.....
int anArray[ ] = { 1, 2, 3}; //一个具有三个元素的数组
const int anArraySize = sizeof( anArray ) / sizeof(anArray[0]); // == 3
average( anArray); //合法
这种从数组到指针的自动转换称为“退化”,即数组退化为指向其首元素的指针。同样的,一个函数型参数会退化成一个函数指针。
2、由于在数组形参中数组边界被忽略了,因此通常在声明时最好将其省略。然而,如果函数期望接受一个指向一个元素序列(换句话说是数组)的指针作为参数,而不是指向单个对象的指针,那么最好这样声明:
void average( int ary[ ]); //形参ary仍然是一个int *
另一方面,如果数组边界的精确数值非常重要,并且希望函数只接受含有特定数量的元素的数组,可以考虑使用一个引用形参:
void average( int (&ary) [12] );
现在函数就只能接受大小为12的整型数组:
average (anArray); //错误!anArray是一个int [ 3 ]
模版有助于代码的泛化:
template <int n >
void average(int (&ary) [n] ); //让编译器帮我们推导n的值
不过,一般做法是将数组的大小明确的传入函数:
void average_n( int ary[ ], int size );
3、使用数组作为函数参数最大的问题在于,数组的大小必须以形参的方式显式地编码,并以单独的实参传入,或者在数组内部以一个结束符值作为指示(例如用于指示“用作字符串的字符数组”之末尾的'\0')。
另一个困难在于,不管数组是如何声明的,一个数组通常是通过指向其首元素的指针进行操纵的。如果那个指针作为实参被传递给函数,我们前面的声明引用形参的技巧将无济于事。
int *anArray2 = new int [ anArraySize];
//.....
average( anArray2 ); //错误,不可以使用int *初始化int (&) [n]
average_n( anArray, anArraySize ); //ok
出于这些原因,经常采用某种标准容器(vector或string)来代替对数组的大多数传统的用法,并且常优先考虑用标准容器。
4、多维数组是数组的数组,因此形参是一个指向数组的指针。