c++编程的时,很多时候,我们需要给给一个函数传入一个数组的长度,不过因为c和c++在传入时,只是将数组的头指针地址(或者引用)传入,我们就无法确知数组长度了。也许有些人表示怀疑,接下来我们来看下面的一个实验:
#include<stdio.h>
#define GET(arr11,len) {len=(sizeof(arr)/sizeof(arr[0]));} //采用宏求解函数长度
int arrLength(int *arr);
int main()
{
int arr[]={1,2,3,4};
//printf("%d\n",arrLength(arr));
int len;
GET(arr,len);
printf("%d\n",len);
printf("%d\n",arrLength(arr));
printf("%d\n",sizeof(arr)/sizeof(int)); //这边结果为4
return 0;
}
int arrLength(int *arr) //输出结果为1,我们可以发现传入的是指针了
{
return(sizeof(arr)/sizeof(int));
}
//int arrLength(int *arr)
//{
// int count=0;
// while(arr!=NULL)
// {
// count++;
// arr++;
// }
// return count;
//}
输出结果为 4 1 4;
在这里,大家是否对注释掉的那段代码感到好奇呢,不妨大家试试看,结果并不是我们想要的,因为 arr!=NULL这个条件不成立时,并不是数组结束的位置。究其原因是内存为arr开辟了一个空间,在内存中很有可能在arr后面的那段存储空间所存储的内容(比如存了0x343432)用指针解释的话也是可行的,并没有指向空。
那么回到我们要讨论的主题:如何传入数组长度呢
方法一:直接传入数组长度;
方法二:使用非类型模板形参;
看下面的例子:
#include<iostream>
using namespace std;
void array_init(int *parm,size_t length)
{
for(size_t i=0;i!=length;i++)
{
parm[i];
cout<<parm[i]<<" ";
}
cout<<endl;
}
template <size_t N>void array_init2(int (&parm)[N]) //非类型模板形参
{
for(size_t i=0;i!=N;i++)
{
parm[i]=i;
cout<<parm[i]<<" ";
}
cout<<endl;
}
template <size_t N> size_t array_length(int (&parm)[N]) //非类型模板形参
{
return N;
}
int main()
{
int arr1[10]={0};
int arr2[10]={0};
array_init(arr1,10); //我们需要传入数组长度
array_init2(arr2); //我们这里并没有传入数组长度哦!这就时使用了非类型模板
cout<<"the length of arr is: "<<array_length(arr2)<<endl;
return 0;
}
输出结果为
其实原理是很简单的,如果我们直接将数组名传给一个函数,数组将退化为一个指针,所以编译器自然也就无法用指针来推导维数了。但是我们强调传的是引用的话,编译器就明确知道这是一个数组,所以就去推导维数。