1.2. Динамические массивы
Если до начала работы программы неизвестно, сколько в массиве элементов, в программе используют динамические массивы. Память под них выделяется с помощью операции new или функции malloc во время выполнения программы. Адрес начала массива хранится в переменной, называемой указателем. Например.
Примечание. Обнуление памяти при ее выделении не происходит.
Инициализировать динамический массив нельзя.
Обращение к элементу динамического массива осуществляется также, как и к элементам обычного массива.
Например, a[0], a[1], …, a[19], c[2][5] и т.д.
Другой способ обращения к элементу b[i][j] двумерного массива имеет вид: *(*(b+i)+j). Поясним это. Двумерный массив представляет собой массив массивов, т.е., это массив, каждый элемент которого является массивом. Имя двумерного массива также является константным указателем на начало массива. Например, int b[5][10] является массивом, состоящим из 5-ти массивов. Для обращения к b[i][j] сначала требуется обратиться к i-ой строке массива, т.е., к одномерному массиву b[i]. Для этого надо к адресу начала массива b прибавить смещение, равное номеру строки i: b+i (при сложении указателя b с i учитывается длина адресуемого элемента, т.е., i·(10·sizeof(int)), т.к. элементом массива b[i] является строка, состоящая из 10 элементов типа int). Затем требуется выполнить разадресацию: *(b+i). Получим массив из 10 элементов. Далее требуется обратиться к j-му элементу полученного массива Для получения его адреса опять применяется сложение указателя с j: *(b+i)+j (на самом деле прибавляется j·sizeof(int)). Затем применяется операция разадресации: *(*(b+i)+j). Т.о., получаем формулу для вычисления адреса элемента b[i][j]:
b+k·i·n+k·j=b+k·(i·n+j),
где k – длина в байтах одного элемента массива, b – адрес начала массива. Эта формула может быть использована в дальнейшем, например для организации передачи в подпрограмму двумерного массива переменной размерности.
Приведем универсальный способ выделения памяти под двумерный массив, когда обе его размерности задаются на этапе выполнения программы:
int i, m, n; //i – номер строки, m, n – количество строк и столбцов
puts("Введите m и n");
scanf("%d %d",&m, &n); // Ввод m, n
int **b=new int *[m]; //1
fot (i=0; i<m; i++) //2
b[i]=new int[n]; //3
Здесь в операторе //1 объявляется переменная типа "указатель на указатель на int" и выделяется память под массив указателей на строки массива (m строк). В операторе //2 организуется цикл для выделения памяти под каждую строку массива. В операторе //3 выделяется память под каждую строку массива и i-му элементу массива указателей на строки присваивается адрес начала участка памяти, выделенного под строку двумерного массива. Каждая строка массива состоит из n элементов типа int.
Примечание. Для выделения динамической памяти для вещественного двумерного массива достаточно в приведенном фрагменте программы в стоках //1, //3 имя типа int поменять на имя типа float.
Освобождение выделенной динамической памяти.
Динамическая память освобождается с помощью операции delete[] имя массива, например, для одномерного массива, delete[]a; Освобождение памяти, выделенной для двумерного массива b, выглядит следующим образом:
fot (i=0; i<n; i++)
delete [ ] b[i];
delete [ ] b;
Время "жизни" динамического массива определяется с момента выделения динамической памяти до момента ее освобождения.