最近看《C++ Primer》中函数模板中一章,有这样一个例子:
template <class Type , int size>
Type min(Type (&r_array)[size])
{
cout << "The lenght of the array : " << size << endl;
Type min_val = r_array[0];
for(int i = 0;i < size; ++ i)
{
if(r_array[i] < min_val)
min_val = r_array[i];
}
return min_val;
return 0;
}
这个函数模板可以自动实现数组长度的传递,从而避免了在函数中手动指定数组的长度。
但是,如果将函数的数组形参作为这个模板的实参时,
void getmin(double mi[ ])
{
min(mi);
}
将会出现编译错误: 对“min(double *&)”的调用没有匹配的函数
这种情况也很好理解,因为数组的作为函数的非引用形参时,实际传入的是数组的首地址,并没有数组的长度信息。当前的函数模板自然不能进行匹配。
于是对函数进行修改,将形参进行修改,改成数组的引用:o
void getmin (double (&mi)[])
{
min(mi);
}
此时没有指定形参中数组引用的数组长度值。编译的时候再次出错:形参mid包含了指向具有未知边界数组‘double []’ 的引用。
于是指定形参中数组的长度,将函数再次修改为:
void getmin (double (&mi)[10])
{
min(mi);
}
但是再次发现问题,当前已经申明了一个数组,double a[3] = {1.0 , 2.4 , 4.1};
当将数组a作为函数getmin的实参是,再次报错:将类型为‘double (&)[10]’的引用初始化为类型为‘double [3]’的表达式无效
也就是说当使用数组的引用作为函数的实参时,必须指定形参中数组的长度。而且这一长度必须与你将来需要作为当前函数的实参数组的长度一致。
这就使得用数组的引用作为函数的形参这一方法变得毫无意义。
为了更进步了解当使用数组的引用和非引用两种情况下,进行参数传递分别是什么操作。我在网上进行了进一步的检索,得到如下解释:
当编译器检查数组形参关联的实参时,它只会检查实参是不是指针、指针的类型和数组元素的类型时是否匹配,而不会检查数组的长度。
如果形参是数组的引用,编译器不会将数组实参转化为指针,而是传递数组的引用本身。在这种情况下,数组大小成为形参和实参类型的一部分。编译器检查数组的实参的大小与形参的大小是否匹配。int (&arr)[10]在这个程序中,数组的大小是经过严格检查的,为了实现传递任意大小的数组,可以考虑建立模板函数的方法:
建立一个可以传递任意大小数组的模板函数:
template <class Type, size_t N>
void somefunction(Type(&parm)[N]){/*some things...*/}
这就非常有趣了,转了一圈又回到我们最开始的函数模板中来了。