Динамические массивы
Для того чтобы создать в динамической области некоторый объект необходима одна обычная (не динамическая переменная) переменная-указатель. Сколько таких объектов нам понадобится для одновременной обработки – столько необходимо иметь обычных переменных-указателей. Таким образом, проблема “задач неопределенной размерности” созданием одиночных динамических объектов решена быть не может.
Решить эту проблему поможет возможность создавать в динамической области памяти массивы объектов с таким количеством элементов, которое необходимо в данный момент работы программы – то есть создание динамических массивов. Действительно, для представления массива требуется всего одна переменная-указатель, а в самом массиве, на который ссылается этот указатель, может быть столько элементов, сколько требуется в данный момент времени.
Сначала рассмотрим одномерные динамические массивы.
Для создания одномерного динамического массива, элементами которого являются, например, действительные числа, используется следующий синтаксис инструкции new:
double *Arr = new double [1000];
Здесь в динамической области памяти будет выделено пространство на 1000 значений типа double, и адрес этой области будет присвоен переменной-указателю Arr. Таким образом, переменная-указатель Arr, как и переменная для обычного массива, будет содержать адрес первого элемента массива.
Освободить динамическую область от этого массива можно так:
delete [ ] Arr;
После этого участок памяти объемом 1000 * sizeof ( double ) байт будет возвращен в список свободной памяти и может быть повторно использован для размещения других динамических объектов.
С помощью функций malloc и calloc тот же самый одномерный динамический массив создается так:
double *Arr = (double *) malloc(1000 * sizeof (double ) );
или
double *Arr = (double *) сalloc(1000, sizeof (double ) );
Освобождение памяти в этих случаях осуществляется с помощью функции free:
Free ( Arr );
Работа с одномерным динамическим массивом осуществляется так же, как и с обычным. Рассмотрим пример, в котором создадим динамический массив целых с количеством элементов, введенном с клавиатуры; заполним его случайными значениями в диапазоне от 1 до 100; подсчитаем и выведем на экран среднее значение всех элементов этого массива:
int n;// Количество элементов массива
cin >> n;// Вводим количество элементов массива с клавиатуры
int *Arr = new int [ n ];// Создаем массив Arrцелых чисел на n элементов
for ( int i = 0; i < n; ++ i)// Заполняем массив случайными значениями
Arr [ i ] = rand ( ) % 100 + 1;
int Sum = 0;// Сумма элементов массива
for ( int i = 0; i < n; ++ i )// Подсчитываем сумму элементов массива
Sum += Arr [ i ];
cout << (double) Sum / n << endl;// Выводим на экран среднее значение
delete [ ] Arr;// Освобождаем память
Очень часто в процессе работы программы требуется изменять размеры уже созданных и заполненных данными массивов. Общий алгоритм решения этой задачи таков:
1. создать исходный массив размерности N1 и заполнить его данными;
2. создать промежуточный массив размерности N2 (пусть N2 > N1);
3. скопировать данные из исходного массива в промежуточный массив;
4. освободить память от исходного массива;
5. переменной-указателю исходного массива присвоить значение переменной-указателя промежуточного массива;
6. заполнить новые элементы массива данными.
Вот как можно решить эту задачу в стиле C++:
int N1 = 10,// Начальный размер массива
N2 = 20;// Новый размер массива
int *Arr = new int [N1];// Создаем исходный массива из N1 элемента
for (int i = 0; i < N1; ++ i)// Заполняем исходный массив числами от 0 до 9
Arr[i] = i;
for (int i = 0; i < N1; ++ i)// Выводим исходный массив на экран
cout << Arr[i] << " ";
cout << endl;
int *Rez = new int [N2];// Создаем промежуточный массив из N2 элементов
for (int i = 0; i < N1; ++ i)// Копируем данные из исходного массива
Rez[i] = Arr[i];// в промежуточный
delete [ ] Arr;// Освобождаем память от исходного массива. Если этого не
// сделать, произойдет утечка памяти
Arr = Rez;// Изменяем переменную исходного массива
for (int i = N1; i < N2; ++ i)// Дополняем исходный массив числами от 10 до 19
Arr[i] = i;
for (int i = 0; i < N2; ++ i)// Снова выводим исходный массив на экран
cout << Arr[i] << " ";
cout << endl;
delete [ ] Arr;// Окончательно освобождаем память от исходного массива.
В результате работы этого фрагмента программы на экран будут выведены значения массива до его расширения и после расширения: