При традиционном определении массива:
тип имя_массива [количество_элементов];
общее количество памяти, выделяемой под массив, задается определением и равно
количество_элементов * sizeof(тип).
Но иногда бывает нужно чтобы память
под массив выделялась для решения конкретной задачи, причем ее размеры заранее
не известны и не могут быть фиксированы.
Формирование
массивов с переменными размерами можно организовать с помощью указателей и
средств динамического распределения памяти двумя способами:
1)
с использованием библиотечных функций,
описанных в заголовочных файлах alloc.h и stdlib.h (стандартный
Си);
2)
с использованием операций new и delete (Си++).
1.1.
Формирование динамических массивов с
использованием библиотечных функций
Для выделения и освобождения динамической памяти используются
функции
|
Функция |
Прототип
и краткое описание |
|
malloc |
void * malloc(unsigned s) Возвращает указатель на начало области динамической памяти
длиной в s байт, при неудачном
завершении возвращает NULL |
|
calloc |
void *
calloc(unsigned n, unsigned m) Возвращает указатель на начало области динамической памяти
для размещения n элементов
длиной по m
байт каждый, при неудачном завершении возвращает NULL |
|
realloc |
void *
realloc(void * p, unsigned s) Изменяет размер блока ранее выделенной динамической памяти
до размера s
байт, р- адрес начала изменяемого блока, при неудачном
завершении возвращает NULL |
|
free |
void
*free(void p) Освобождает ранее выделенный участок динамической памяти, р – адрес первого байта |
Пример:
Функция для формирования одномерного динамического массива
int * make_mas(int n)
(
int *mas;
mas=(int*)malloc(n*sizeof(int));
for(int i=0;i<n;i++)
mas[i]=random(10);
return mas;
}
Для
выделения памяти используется функция malloc, параметром
которой является размер выделяемого участка памяти равный n*sizeof(int). Так как функция malloc возвращает нетипизированный указатель void*, то необходимо выполнить
преобразование полученного нетипизированного указателя в указатель int*.
Освободить
выделенную память можно функцией free(mas).
1.2.
Формирование динамических массивов с
использованием операций new и delete
Для динамического распределения памяти
используются операции new и delete.
Операция
new имя_типа
или
new имя_типа инициализатор
позволяет выделить и сделать
доступны свободный участок памяти, размеры которого соответствуют типу данных,
определяемому именем типа. В выделенный участок заносится значение
определяемое инициализатором, который не является обязательным параметром. В
случае успешного выделения памяти операция возвращает адрес начала выделенного
участка памяти, если участок не может быть выделен, то возвращается NULL.
Примеры:
1) int *i;
i=new int(10);
2) float
*f;
f=new float;
3)
int *mas=new[5];
В примерах 1, 2 показано как выделить память под скалярные переменные, пример 3
показывает выделение памяти под массив переменных.
Операция delete
указатель освобождает участок памяти ранее выделенный
операцией new.
Пример:
Функция для формирования двумерного динамического массива
int ** make_matr(int n)
{
int **matr;
int i,j;
matr=new int*[n];
for (i=0;i<n;i++)
{
matr[i]=new int[n];
for (j=0;j<n;j++)
matr[i][j]=random(10);
};
return
matr;
}
При формировании матрицы сначала
выделяется памяти для массива указателей на одномерные массивы, а затем в цикле
с параметром выделяется память под n
одномерных массивов.
**matr
|
*matr[1] |
*matr[2] |
*matr[3] |
. . . . |
*matr[n] |
![]()
![]()
![]()
![]()
Чтобы освободить память необходимо
выполнить цикл для освобождения одномерных массивов
for(int
i=0;i<n;i++)
delete matr[i];
После этого освобождаем память на которую указывает указатель matr
delete [] matr;