Многомерный массив — это довольно ёмкое и непростое понятие. Начнем с того, что в С++ массивы бывают статическими и динамическими. Статические массивы в C++ — это массивы, которые инициализируются при запуске программы и имеют фиксированный размер. Объявляются они так:
int ar[3][5] = { { 1, 2, 3, 4, 5 }, { 2, 4, 6, 8, 10 }, { 3, 6, 9, 12, 15 } };
Вышеприведенный массив ar можно рассматривать как массив 3-х массивов из 5-ти чисел типа int. Число пять характеризует размерность подмассивов
, или размерность второго измерения. Выделение памяти для них, как правило, происходит на стэке. Это и есть что ни на есть прямоугольный многомерный массив.
Важно понять, что любой статический массив является прямоугольным. Все неинициализированные вами значения компилятор инициализирует нулем автоматически, как в примере ниже:
int ar[][5] = { { 1, 2, 3}, { 2, 4, 6, 8, 10 }, { 3, 6, 9, 12, 15 } }; cout << ar[0][4] << endl; //0
Кстати, вы можете не указывать размер 1-го массива, как в примере выше. Но второй — должен быть обязательно.
Помимо всего прочего можно так же инициализировать значение нулем, как и одномерный int array[3][5] = { 0 };
Передавать в функцию эти массивы можно так: void func(int ary[][5]) { }
Тут нет ничего сложного. Перейдем к теме
Динамические массивы
Объявление динамических массивов в C++ имеет следующий синтаксис:
int** ary = new int * [10]; ary[0]=new int [5];
В вышеприведенном примере объявлен массив, содержащий 10 других одномерных массивов типа int 10 потенциальных указателей на массивы типа int
. Почему потенциальных? Потому что они еще не назначены. Во второй строке мы объявили один из таких десяти массивов и присвоили первому элементу массива ar
указатель на него.
Фактически мы получили такой же многомерный массив, как и выше. Но теперь он не обязан быть прямоугольным: второе измерение массива ar является неопределенным и меняется от элемента к элементу, а так же не являются постоянным в течение работы программы. Именно поэтому они и получили название динамических. Иногда их называют зубчатыми.
В C++ память под такие массивы, как и под любые объекты, память под которые выделена через оператор new, располагается в куче. Поэтому весьма важно помнить, что каждый массив необходимо потом удалить из памяти. И для этого недостаточно просто написать delete[] ar
, как для одномерного. Необходимо пройтись по каждому элементу массива:
for (int i = 0; i < dim1; i++) { delete [] ar[i]; }
Еще важная деталь, касающаяся динамических массивов в том, что размер нельзя просто так определить функцией sizeof. Поэтому при передаче в функцию обязательно передается и размерность элементов, чтобы избежать глупых ошибок, связанных с выходом за пределы диапазона
Теперь перейдем к C#:
Статические массивы в C# определяются так
int[,] ar = { { 0, 1, 2 }, { 3, 4, 5 } };
Это объявление массива полностью эквивалентно объявлению статического многомерного массива в C++.
В данном случае мы получили два массива размерностью 3. Расположены они будут так же на стеке, правда правила размещения в шарпе несколько отличаются от с++. Например
int[,,] ar = new int[2, 3, 4];
будет располагаться на стеке, поскольку все простые типы в шарпе живут там, независимо от применения new
. Но как и в C++, такие массивы должны быть инициализированы при старте/компиляции программы
Что же насчет динамических массивов?
Они так же есть, выглядят несколько иначе и объявляются так:
int[][] ar = new int[3][];//объявление ar[0] = new int[2] { 1, 2 }; //инициализация элемента
Располагаются так же в стеке, если это не массив экземпляров класса.
На сим откланяюсь