以下代码对我来说效果很好。
#include <iostream>
using namespace std;
template<class T>
T sum_array(T (&a)[10], int size)
{
T result=0;
for(int i=0; i<size; i++)
{
result = a[i] + result;
}
return result;
}
int main()
{
int a[10] = {0,1,2,3,4,5,6,7,8,9};
cout<<sum_array(a, 10)<<endl;
double d[10] = {1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1,1.1};
cout<<sum_array(d, 10)<<endl;
cin.get();
}
但是如果尝试通过删除数组大小使我的函数更通用,如下面的函数所示,它会给出一个错误,说明没有函数模板的实例。
template<class T>
T sum_array(T (&a)[], int size)
{
T result=0;
for(int i=0; i<size; i++)
{
result = a[i] + result;
}
return result;
}
同时,如果我删除了如下所示的引用,它就可以正常工作。
template<class T>
T sum_array(T a[], int size)
{
T result=0;
for(int i=0; i<size; i++)
{
result = a[i] + result;
}
return result;
}
我对模板比较新,请您解释一下上面的行为。
答案 0 :(得分:2)
在funciton参数中,[]
(内部没有维度)只是指针的替代语法,因为数组在传递给函数时会衰减为指针,除非它们通过引用传递。
这意味着您的工作通用模板(T a[]
)与T a*
完全相同。如果你在运行时传递大小,一切都很好,你可以使用它(它将适用于未声明为数组的其他东西,例如std::string::c_str()
的返回值)。
但是,如果你想推广tempalte但仍然限于实际的数组,你可以这样做:
template<class T, size_t N>
T sum_array(T (&a)[N], int size)
{
T result=0;
for(int i=0; i<size; i++)
{
result = a[i] + result;
}
return result;
}
这样,只能传入一个真正的数组,但它的类型T
和长度N
都将被推导出来。根据您的使用情况,您可能会在这种情况下删除size
参数。
答案 1 :(得分:0)
如果要通过引用绑定数组,则绝对需要知道数组的大小。但可以让编译器推断出大小。假设代码中的逻辑非常重要,最好立即委托给独立于数组大小的版本。这是一个例子:
template<typename T>
T sum_array(T const* a, int size)
{
return std::accumulate(a, a + size, T());
}
template <typename T, int Size>
T sum_array(T const (&array)[Size]) {
return sum_array(array, Size);
}
当然,我无法抗拒使用std::accumulate()
中的<numeric>
:如果有算法,最好使用它。
由于您想知道从数组中删除引用:当使用T[]
作为函数参数的类型时,它等同于使用T*
。即使您使用T[10]
作为函数参数的类型,编译器也会将其读作T*
。