Динамическое выделение памяти необходимо для эффективного использования памяти компьютера. Например, мы написали какую-то программку, которая обрабатывает массив. При написании данной программы необходимо было объявить массив, то есть задать ему фиксированный размер (к примеру, от 0 до 100 элементов). Тогда данная программа будет не универсальной, ведь может обрабатывать массив размером не более 100 элементов. А если нам понадобятся всего 20 элементов, но в памяти выделится место под 100 элементов, ведь объявление массива было статическим, а такое использование памяти крайне не эффективно.
В С++ операции new
и delete
предназначены для динамического распределения памяти компьютера. Операция new
выделяет память из области свободной памяти, а операция delete
высвобождает выделенную память. Выделяемая память, после её использования должна высвобождаться, поэтому операции new
и delete
используются парами. Даже если не высвобождать память явно, то она освободится ресурсами ОС по завершению работы программы. Рекомендую все-таки не забывать про операцию delete
.
// пример использования операции new int *ptrvalue = new int; //где ptrvalue – указатель на выделенный участок памяти типа int //new – операция выделения свободной памяти под создаваемый объект.
Операция new
создает объект заданного типа, выделяет ему память и возвращает указатель правильного типа на данный участок памяти. Если память невозможно выделить, например, в случае отсутствия свободных участков, то возвращается нулевой указатель, то есть указатель вернет значение 0. Выделение памяти возможно под любой тип данных: int, float,double, char
и т. д.
// пример использования операции delete: delete ptrvalue; // где ptrvalue – указатель на выделенный участок памяти типа int // delete – операция высвобождения памяти
Разработаем программу, в которой будет создаваться динамическая переменная.
// new_delete.cpp: определяет точку входа для консольного приложения. #include "stdafx.h" #include <iostream> using namespace std; int main(int argc, char* argv[]) { int *ptrvalue = new int; // динамическое выделение памяти под объект типа int *ptrvalue = 9; // инициализация объекта через указатель //int *ptrvalue = new int (9); инициализация может выполнятся сразу при объявлении динамического объекта cout << "ptrvalue = " << *ptrvalue << endl; delete ptrvalue; // высвобождение памяти system("pause"); return 0; }
// код Code::Blocks
// код Dev-C++
// new_delete.cpp: определяет точку входа для консольного приложения. #include <iostream> using namespace std; int main(int argc, char* argv[]) { int *ptrvalue = new int; // динамическое выделение памяти под объект типа int *ptrvalue = 9; // инициализация объекта через указатель //int *ptrvalue = new int (9); инициализация может выполнятся сразу при объявлении динамического объекта cout << "ptrvalue = " << *ptrvalue << endl; delete ptrvalue; // высвобождение памяти return 0; }
В строке 10 показан способ объявления и инициализации девяткой динамического объекта, все, что нужно так это указать значение в круглых скобочках после типа данных. Результат работы программы показан на рисунке 1.
ptrvalue = 9 Для продолжения нажмите любую клавишу . . .
Рисунок 1 — Динамическая переменная
Создание динамических массивов
Как было сказано раньше, массивы также могут быть динамическими. Чаще всего операции new
и delete
применяются для создания динамических массивов, а не для создания динамических переменных. Рассмотрим фрагмент кода создания одномерного динамического массива.
// объявление одномерного динамического массива на 10 элементов: float *ptrarray = new float [10]; // где ptrarray – указатель на выделенный участок памяти под массив вещественных чисел типа float // в квадратных скобочках указываем размер массива
После того как динамический массив стал ненужным, нужно освободить участок памяти, который под него выделялся.
// высвобождение памяти отводимой под одномерный динамический массив: delete [] ptrarray;
После оператора delete ставятся квадратные скобочки, которые говорят о том, что высвобождается участок памяти, отводимый под одномерный массив. Разработаем программу, в которой создадим одномерный динамический массив, заполненный случайными числами.
// new_delete_array.cpp: определяет точку входа для консольного приложения. #include "stdafx.h" #include <iostream> // в заголовочном файле <ctime> содержится прототип функции time() #include <ctime> // в заголовочном файле <iomanip> содержится прототип функции setprecision() #include <iomanip> using namespace std; int main(int argc, char* argv[]) { srand(time(0)); // генерация случайных чисел float *ptrarray = new float [10]; // создание динамического массива вещественных чисел на десять элементов for (int count = 0; count < 10; count++) ptrarray[count] = (rand() % 10 + 1) / float((rand() % 10 + 1)); //заполнение массива случайными числами с масштабированием от 1 до 10 cout << "array = "; for (int count = 0; count < 10; count++) cout << setprecision(2) << ptrarray[count] << " "; delete [] ptrarray; // высвобождение памяти cout << endl; system("pause"); return 0; }
// код Code::Blocks
// код Dev-C++
// new_delete_array.cpp: определяет точку входа для консольного приложения. #include <iostream> // в заголовочном файле <ctime> содержится прототип функции time() #include <ctime> // в заголовочном файле <iomanip> содержится прототип функции setprecision() #include <iomanip> #include <cstdlib> using namespace std; int main(int argc, char* argv[]) { srand(time(0)); // генерация случайных чисел float *ptrarray = new float [10]; // создание динамического массива вещественных чисел на десять элементов for (int count = 0; count < 10; count++) ptrarray[count] = (rand() % 10 + 1) / float((rand() % 10 + 1)); //заполнение массива случайными числами с масштабированием от 1 до 10 cout << "array = "; for (int count = 0; count < 10; count++) cout << setprecision(2) << ptrarray[count] << " "; delete [] ptrarray; // высвобождение памяти cout << endl; system("pause"); return 0; }
Созданный одномерный динамический массив заполняется случайными вещественными числами, полученными c помощью функций генерации случайных чисел, причём числа генерируются в интервале от 1 до 10, интервал задается так — rand() % 10 + 1
. Чтобы получить случайные вещественные числа, выполняется операция деления, с использованием явного приведения к вещественному типу знаменателя — float((rand() % 10 + 1))
. Чтобы показать только два знака после запятой используем функцию setprecision(2)
, прототип данной функции находится в заголовочном файле <iomanip>
. Функция time(0)
засевает генератор случайных чисел временным значением, таким образом, получается, воспроизводить случайность возникновения чисел (см. Рисунок 2).
array = 0.8 0.25 0.86 0.5 2.2 10 1.2 0.33 0.89 3.5 Для продолжения нажмите любую клавишу . . .
Рисунок 2 — Динамический массив в С++
По завершению работы с массивом, он удаляется, таким образом, высвобождается память, отводимая под его хранение.
Как создавать и работать с одномерными динамическими массивами мы научились. Теперь рассмотрим фрагмент кода, в котором показано, как объявляется двумерный динамический массив.
// объявление двумерного динамического массива на 10 элементов: float **ptrarray = new float* [2]; // две строки в массиве for (int count = 0; count < 2; count++) ptrarray[count] = new float [5]; // и пять столбцов // где ptrarray – массив указателей на выделенный участок памяти под массив вещественных чисел типа float
Сначала объявляется указатель второго порядка float **ptrarray
, который ссылается на массив указателей float* [2]
, где размер массива равен двум. После чего в цикле for
каждой строке массива объявленного в строке 2 выделяется память под пять элементов. В результате получается двумерный динамический массив ptrarray[2][5]
. Рассмотрим пример высвобождения памяти отводимой под двумерный динамический массив.
// высвобождение памяти отводимой под двумерный динамический массив: for (int count = 0; count < 2; count++) delete [] ptrarray[count]; // где 2 – количество строк в массиве
Объявление и удаление двумерного динамического массива выполняется с помощью цикла, так как показано выше, необходимо понять и запомнить то, как это делается. Разработаем программу, в которой создадим двумерный динамический массив.
// new_delete_array2.cpp: определяет точку входа для консольного приложения. #include "stdafx.h" #include <iostream> #include <ctime> #include <iomanip> using namespace std; int main(int argc, char* argv[]) { srand(time(0)); // генерация случайных чисел // динамическое создание двумерного массива вещественных чисел на десять элементов float **ptrarray = new float* [2]; // две строки в массиве for (int count = 0; count < 2; count++) ptrarray[count] = new float [5]; // и пять столбцов // заполнение массива for (int count_row = 0; count_row < 2; count_row++) for (int count_column = 0; count_column < 5; count_column++) ptrarray[count_row][count_column] = (rand() % 10 + 1) / float((rand() % 10 + 1)); //заполнение массива случайными числами с масштабированием от 1 до 10 // вывод массива for (int count_row = 0; count_row < 2; count_row++) { for (int count_column = 0; count_column < 5; count_column++) cout << setw(4) <<setprecision(2) << ptrarray[count_row][count_column] << " "; cout << endl; } // удаление двумерного динамического массива for (int count = 0; count < 2; count++) delete []ptrarray[count]; system("pause"); return 0; }
// код Code::Blocks
// код Dev-C++
// new_delete_array2.cpp: определяет точку входа для консольного приложения. #include <iostream> #include <ctime> #include <iomanip> #include <cstdlib> using namespace std; int main(int argc, char* argv[]) { srand(time(0)); // генерация случайных чисел // динамическое создание двумерного массива вещественных чисел на десять элементов float **ptrarray = new float* [2]; // две строки в массиве for (int count = 0; count < 2; count++) ptrarray[count] = new float [5]; // и пять столбцов // заполнение массива for (int count_row = 0; count_row < 2; count_row++) for (int count_column = 0; count_column < 5; count_column++) ptrarray[count_row][count_column] = (rand() % 10 + 1) / float((rand() % 10 + 1)); //заполнение массива случайными числами с масштабированием от 1 до 10 // вывод массива for (int count_row = 0; count_row < 2; count_row++) { for (int count_column = 0; count_column < 5; count_column++) cout << setw(4) <<setprecision(2) << ptrarray[count_row][count_column] << " "; cout << endl; } // удаление двумерного динамического массива for (int count = 0; count < 2; count++) delete []ptrarray[count]; system("pause"); return 0; }
При выводе массива была использована функция setw()
, если вы не забыли, то она отводит место заданного размера под выводимые данные. В нашем случае, под каждый элемент массива по четыре позиции, это позволяет выровнять, по столбцам, числа разной длинны (см. Рисунок 3).
2.7 10 0.33 3 1.4 6 0.67 0.86 1.2 0.44 Для продолжения нажмите любую клавишу . . .
Рисунок 3 — Динамический массив в С++
Комментарии
Никита Абраменко
А можно ли удалять отдельные элементы массива