数组有两个特殊的性质,影响我们定义和使用作用在数组上的函数:一是不能复制数组。二是使用数组名字时,数组会自动转换为指向其第一个元素的指针。因为数组不能复制,所以无法编写使用数组类型形参的函数。因为数组会被初始化为指针,所以处理数组的函数通常通过操作指向数组中的元素的指针来处理数组。
示例:
//形式1
void printValues(const int ia[10]) //虽然形参指定了数组的大小,但编译时不会检查实参数组大小,因为编译器只检查形参是否是指针,并且指针类型和数组元素的类型是否匹配。
{
for(size_t i=0;i!=10;i++)
{
cout<<ia[i]<<endl;
}
}
//形式2
void printValues2(const int ia[],int size)
{
for(size_t i=0;i!=size;i++)
{
cout<<ia[i]<<endl;
}
}
int main(void)
{
int i[10]={1,2,3,4,5,6,7,8,9,0};
printValues(i); //i作为printValues的实参,在这里为数组i的首地址,或者说他转换为成一个指针
printValues2(i,10);
}
数组形参可以定义为引用或非引用类型。大部分情况下,数组以普通的非引用类型传递,此时数组会悄悄的转换为指针。一般来说,非引用类型的形参会初始化为其相应实参的副本。但是在传递数组时,实参是指向数组第一个元素的指针,形参复制的是这个指针的值,而不是数组元素本身。函数操作的也是指针的副本,因此不会修改实参指针的值。然而,函数可通过该指针修改它所指向的数组元素的值。
以上代码可以使用指针表示,效果等同:
void printValues3(const int *ia,int size)
{
for(size_t i=0;i!=size;i++,ia++)
{
cout<<*ia<<endl;
}
}
示例2(通过引用传递数组):
void printValues4(int (&arr)[10]) //这种情况下,数组大小成为形参和实参的一部分。编译器会检查数组大小是否匹配。 int (&arr)[10] 中的小括号是必须的。
{
for(size_t i=0;i!=10;i++)
{
cout<<arr[i]<<endl;
}
}
int main(void)
{
printValues4(i);
}
和其他类型一样,数组形参可声明为数组的引用。如果形参是数组的引用,编译器不会将数组实参转化为指针,而是传递数组的引用本身。