Помимо обычных массивов в C++ предоставляет возможность создавать и многомерные. Рассмотри на примере двумерного массива.
Двумерный массив – объект данных T a[N][M]
, который:
a[N * M]
, что сводит его двумерный характер к удобному умозрительному приему, упрощающему обсуждение и визуализацию порядка размещения данныхМассивы размерности больше двух считаются многомерными, при этом (N+1)-мерные массивы индуктивно определяются как линеаризованные массивы N-мерных массивов, для которых справедливо все сказанное об одно- и двумерных массивах.
int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
int b[2][3] = {{0, 1}, {2, 3, 4}};
int c[2][3] = {0, 1, 2, 3, 4};
/*
результаты:
a: {1, 2, 3, 4, 5, 6}
b: {0, 1, 0, 2, 3, 4}
c: {0, 1, 2, 3, 4, 0}
*/
// определение массивов размерности больше 2
double d[3][5][10];
Для доступа ко всем элементам двумерного массива требуется два цикла: один для строк и один для столбцов. Поскольку доступ к двумерным массивам обычно выполняется по строкам, то левый индекс используется в качестве внешнего цикла:
for (int row = 0; row < numRows; ++row) // доступ по строкам
for (int col = 0; col < numCols; ++col) // доступ к каждому элементу в строке
cout << array[row][col];
Для многомерных массивов справедлив ряд тождеств, отражающих эквивалентность соответствующих выражений языка С. Так для двумерного массива T a[N][M]
справедливо:
a == &a[0]; a + I == &a[i];
*a == a[0] == &a[0][0];
**a == *&a[0][0] == a[0][0];
a[i][j] == *(*(a + i) + j);
Использование операции разыменования *
не имеет каких-либо преимуществ перед доступом по индексу, и наоборот.
Проилюстрируем создание двумерного массива:
int **m = new int *[5];
for (int i = 0; i < 5; i+)
m[i] = new int[4];