通过引用c ++中的模板函数传递数组

时间:2013-11-23 14:22:42

标签: c++ templates

以下代码对我来说效果很好。

#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;
}

我对模板比较新,请您解释一下上面的行为。

2 个答案:

答案 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*