【问题标题】:Passing an array by reference to template function in c++通过引用 C++ 中的模板函数来传递数组
【发布时间】:2013-11-23 14:22:42
【问题描述】:

下面的代码对我来说很好。

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

我对模板比较陌生,你能解释一下上述行为吗?

【问题讨论】:

  • 在这种情况下最好使用std::array&lt;double&gt;

标签: c++ templates


【解决方案1】:

在函数参数中,[](内部没有维度)只是指针的替代语法,因为数组在传递给函数时会衰减为指针,除非它们通过引用传递。

这意味着您的通用通用模板(带有T a[] 的模板)与T a* 完全相同。如果你在运行时传递大小,一切都很好,你可以使用它(它适用于其他未声明为数组的东西,例如std::string::c_str()的返回值)。

但是,如果您想概括模板但仍将其限制为实际数组,您可以这样做:

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 参数。

【讨论】:

  • 可以改成template T sum_array(T (&a)[N])。读者可能看不懂你的最后一行。
【解决方案2】:

如果你想通过引用绑定一个数组,你绝对需要知道数组的大小。但是,您可以让编译器推断出大小。假设您的代码中的逻辑很重要,最好立即委托给与数组大小无关的版本。这是一个例子:

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

当然,我无法抗拒也使用来自&lt;numeric&gt;std::accumulate():如果有这样的算法,那么使用它是个好主意。

既然你想知道从数组中删除引用:当使用T[]作为函数参数的类型时,它相当于使用T*。即使您使用T[10] 作为函数参数的类型,编译器也会将其读取为T*

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-06
    • 1970-01-01
    相关资源
    最近更新 更多