Динамическое выделение памяти необходимо для эффективного использования памяти компьютера. Например, мы написали какую-то программку, которая обрабатывает массив. При написании данной программы необходимо было объявить массив, то есть задать ему фиксированный размер (к примеру, от 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 — Динамический массив в С++
Комментарии
Никита Абраменко
А можно ли удалять отдельные элементы массива