C ++:按参考二维数组?为什么该功能起作用

时间:2019-04-18 00:42:53

标签: c++ templates multidimensional-array 2d

参数printArray(int(&a)[n] [m])是什么意思?为什么需要括号,为什么只需要向printArray函数提供1值?该函数在调用时如何知道n和m?

template <size_t n, size_t m>
void printArray(int (&a)[n][m]) {
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            cout << a[i][j] << " ";
        }
        cout << endl;
    }
}


int main(int argc, char* argv[])
{
    cout << "Example I:" << endl;
    int ab[2][5];
    printArray(ab);
    cout << "Example II:" << endl;
    int b[2][5] = {{1, 2, 3}};
    printArray(b);
    cout << "Example III:"<< endl;
    int c[][5] = {1, 2, 3, 4, 5, 6, 7};
    printArray(c);
    cout << "Example IV:" << endl;
    int d[][5] = {{1, 2, 3, 4}, {5, 6}, {7}};
    printArray(d);
}

2 个答案:

答案 0 :(得分:3)

  

参数printArray(int (&a)[n][m])是什么意思?

这意味着a是对类型int[n][m]的对象的引用。 int[n][m]m类型的int[n]个对象的数组。 int[n]n类型的int个对象的数组。因此,a是对尺寸为nm的二维数组的引用。

nm是在template <size_t n, size_t m>中声明的模板参数。这两个参数的类型均为size_t,它是整数类型。

  

为什么需要括号

因为&令牌绑定到左侧。 int&是对int的引用。 int& a[n]在语法上意味着a是一个引用数组(但是不允许这种数组)。括号用于消除&令牌是声明对int的引用(数组)还是对数组的引用。

  

为什么只需要向printArray函数提供1个值?

该函数只有一个参数:a。如果传递的值可以绑定到适当类型的数组引用,则它可以工作。在您所有的示例中,参数都是2d整数数组,因此它们是正确的。

  

该函数在调用时如何知道n和m?

编译器知道,因为数组的大小是数组类型的一部分。并且由于模板参数的推导。如果未明确指定模板参数,则可以从函数的参数中推导出模板参数。在这种情况下,如果传递类型为int[2][5]的参数,则将n推导为2,将m推导为5。

您甚至可以添加模板类型参数,然后推导该参数:

template <size_t n, size_t m, typename T>
void printArray(T (&a)[n][m])
如果您要传递二维整数数组,则

T将被推论为int

  

如果不允许引用数组,为什么编译器不能推断出括号是不必要的。

如果int &a[n]表示对数组的引用,因为没有引用数组,那么这会使程序员迷惑int *a[n]不是指向数组的指针,因为可以存在指针数组。

此外,这将为不必要的引用添加特殊情况,从而使语言复杂化。

  

为什么不是这样的形式:printArray(int [n] [m]&a)

更简单地说,为什么不能用int[n] a而不是int a[n]声明数组。因为后者的语法是由C语言的设计师(大概是丹尼斯·里奇,当时是他)选择的。

答案 1 :(得分:1)

它只是通过引用获取一个数组。至于在函数内部使用传递的数组,通常您将编写与其他代码完全相同的代码。唯一的区别是它保留了其数组类型。

当您将数组“按值”传递给函数时,它实际上已衰减为指向其第一个元素的指针。通过引用(或通过地址)传递它可以防止这种用法的这种衰减。

实际上,即使您在参数中为第一个维度指定范围,但如果数组是“按值”传递的,编译器也会忽略它。

这是一个模板编程技巧,可用来推断第一维的范围,否则,如果您编写以下内容,则可能会丢失:

template<size_t m>
void printArray(int a[][m]) {...}

因此,替代方案可能不太整洁:

template<size_t m>
void printArray(int a[][m], size_t n) {...}

需要括号,因为int &a[n][m]是2D引用数组,这是非法的,因为您不能创建引用数组。 int (&a)[n][m]中的括号表示“对int的nxm数组的引用”。