说明:
数组的两个特殊性质对我们定义和使用作用在数组上的函数有影响,这两个性质分别是:
- 不允许拷贝数组;
- 使用数组时通常会将其转换成指针。
因为不能拷贝数组,所以我们无法以值传递的方式使用数组参数。
因为数组会被转换成指针,所以当我们为函数传递一个数组时,实际上传递的是指向数组首元素的指针。
尽管不能以值传递的形式传递数组,但是我们可以把形参写成类似数组的形式:
//尽管形式不同,但这三个print函数是等价的
//每个函数都有一个const int*类型的形参
void print(const int*);
void print(const int[]);
void print(const int[10])//这里的维度表示我们期望数组含有多少元素,实际不一定
当编译器处理对print函数的调用时,只检查传入的参数是否是const int*类型:
int i = 2;
int j[2] = {1,2};
print(&i); //正确,&i的类型是int*
print(j); //正确,j被转换成int*并指向j[0]
如果我们传给print函数的是一个数组,则实参自动地转换成指向首元素的指针,数组的大小对函数的调用没有影响。
案例说明:
下面以一个例子来说明数组作为形参被传递时,传递的是指向数组首元素的指针
#include<iostream>
using namespace std;
int arraylength(int a[])
{
int len = sizeof(a) / sizeof(a[0]);
cout << "len_of_arraylength: " << len << endl;
return 0;
}
int main()
{
int a[13] = { 5, 16, 39, 45, 51, 98, 100, 202, 226, 321, 368, 444, 501 };
int len = sizeof(a) / sizeof(a[0]);
cout << "len_of_main: " << len << endl;
arraylength(a);
return 0;
}
由于数组实际上是以指针的形式传递给函数的,因此一开始函数并不知道数组的确切尺寸,调用者应该为此提供额外的一些信息。管理指针形参有三种常用的技术:
显示传递一个表示数组大小的形参
专门定义一个表示数组大小的形参
#include<iostream>
using namespace std;
//const int a[]等价于const int *a
//len表示数组的大小,将它显示地传给函数用于控制对a元素的访问
void print(const int a[],int len) //显示传递一个表示数组大小的形参
{
for (int i = 0; i < len;i++)
cout <<"a["<<i<<"]="<< a[i]<< endl;
}
int main()
{
int a[6] = { 5, 16, 39, 45, 51, 98};
int len = sizeof(a) / sizeof(a[0]);
print(a,len);
return 0;
}
使用标记指定数组长度
使用标准库函数begin和end
C++11标准引入两个名为begin和end的函数,begin函数返回指向数组首元素的指针,end函数返回指向数组尾元素下一位置的指针,这两个函数定义在iterator头文件中。
示例代码如下:
#include<iostream>
using namespace std;
void print(const int *abeg, const int *aend)
{
while (abeg < aend)
{
cout << *abeg<< " ";
abeg++;
}
cout << endl;
}
int main()
{
int a[6] = { 5, 16, 39, 45, 51, 98 };
int *abeg = begin(a);
int *aend = end(a);
print(abeg,aend);
return 0;
}