C ++: 2D массив по ссылке? Почему эта функция работает - PullRequest
1 голос
/ 18 апреля 2019

Что означает параметр 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 ]

3 голосов
/ 18 апреля 2019

Что означает параметр printArray(int (&a)[n][m])?

Это означает, что a является ссылкой на объект типа int[n][m]. int[n][m] - это массив m объектов типа int[n]. int[n] - это массив n объектов типа int. Так, a является ссылкой на 2d массив с размерами n и m.

n и m являются аргументами шаблона, которые были объявлены в template <size_t n, size_t m>. Тип обоих аргументов: size_t, который является целочисленным типом.

Зачем нужны скобки

Потому что & -token привязывается слева. int& является ссылкой на int. int& a[n] будет синтаксически означать, что a является массивом ссылок (хотя такие массивы недопустимы). Скобки используются для устранения неоднозначности, объявляет ли & -token ссылку (массив) на int или ссылку на массив.

и почему для функции printArray нужно указать только 1 значение?

У функции ровно один аргумент: a. Если вы передаете значение, которое может быть связано с ссылкой на массив соответствующего типа, то это работает. Во всех ваших примерах аргументы - это двумерные массивы целых чисел, поэтому они верны.

как функция узнает 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]. Потому что последний синтаксис был выбран (предположительно Деннисом Ричи, когда он был) разработчиком языка Си.

1 голос
/ 18 апреля 2019

Это просто получение массива по ссылке.Поскольку использование переданного массива идет внутри функции, вы, как правило, будете писать точно такой же код, как в противном случае.Единственное отличие состоит в том, что он сохраняет свой тип массива.

Когда вы передаете массивы "по значению" в функцию, она фактически превращается в указатель на свой первый элемент.Передача его по ссылке (или по адресу) предотвращает это затухание при таком использовании.

Фактически, даже если вы укажете экстент для первого измерения в параметре, компилятор проигнорирует его, если будет передан массив "по значению ".

Это хитрость программирования шаблонов для определения экстента первого измерения, которое в противном случае было бы потеряно, если бы вы написали:

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] - это двумерный массив ссылок, что недопустимо, поскольку вы не можете создать массив ссылок.Скобка в int (&a)[n][m] делает эту «ссылку на массив nxm типа int».

...