Динамическая память
При создании массива с фиксированными размерами под него выделяется определенная память. Например, пусть у нас будет массив с пятью элементами:
double numbers[5] = ;
Для такого массива выделяется память 5 * 8 (размер типа double) = 40 байт. Таким образом, мы точно знаем, сколько в массиве элементов и сколько он занимает памяти. Однако это не всегда удобно. Иногда бывает необходимо, чтобы количество элементов и соответственно размер выделяемой памяти для массива определялись динамически в зависимости от некоторых условий. Например, пользователь сам может вводить размер массива. И в этом случае для создания массива мы можем использовать динамическое выделение памяти.
Для управления динамическим выделением памяти используется ряд функций, которые определены в заголовочном файле stdlib.h :
- malloc() . Имеет прототип
void *malloc(unsigned s);
void *calloc(unsigned n, unsigned m);
void *realloc(void *bl, unsigned ns);
void *free(void *bl);
malloc
Функция malloc() выделяет память длиной для определенного количества байт и возвращает указатель на начало выделенной памяти. Через полученный указатель мы можем помещать данные в выделенную память. Рассмотрим простой пример:
#include #include // для подключения функции malloc int main(void) < int *ptr = malloc(sizeof(int)); // выделяем память для одного int *ptr = 24; // помещаем значение в выделенную память printf("%d \n", *ptr); free(ptr); >
Здесь с помощью функции malloc выделяется память для одного объекта int . Чтобы узнать, сколько байтов надо выделить, передаем в функцию malloc размер типа int на текущей и в результате получаем указатель ptr , который указывает на выделенную память
int *ptr = malloc(sizeof(int));
То есть поскольку int на большинстве архитектур занимает 4 байта, то в большинстве случаев будет выделяться память объемом в 4 байта. Стоит отметить, что мы также могли бы получить размер через разыменование указателя:
int *ptr = malloc(sizeof *ptr);
Для универсальности возвращаемого значения в качестве результата функция malloc() (как и calloc() и realloc() ) возвращает указатель типа void * . Но в нашем случае создается массив типа int, для управления которым используется указатель типа int * , поэтому выполняется неявное приведение результата функции malloc к типу int * .
Далее через этот указатель с помощью операции разыменования помещаем в выделенный участок памяти число 24:
*ptr = 24;
В дальнейшем, используя указатель, можно получить значение из выделенного участка памяти:
printf("%d \n", *ptr);
После завершения работы освобождаем память, передавая указатель в функцию free() :
free(ptr);
Стоит отметить, что теоретически мы можем столкнуться с тем, что функции malloc() не удастся выделить требуемую память, и тогда она возвратит NULL. Чтобы избежать подобной ситуации перед использованием указателя мы можем проверять его на значение NULL:
#include #include // для подключения функции malloc int main(void) < int *ptr = malloc(sizeof(int)); // выделяем память для одного int if(ptr != NULL) < *ptr = 24; // помещаем значение в выделенную память printf("%d \n", *ptr); >free(ptr); >
Немотря на освобождение памяти с помощью функции free() указатель сохраняет свой адрес, и теоретически мы можем обращаться к памяти по данному указателю. Однако полученные значения уже будут неопределенными и недетеминированными. Поэтому некоторые советуют после освобождения памяти также устанавливать для указателя значение NULL :
free(ptr); ptr = NULL;
Выделение памяти для массива
Подобным образом можно выделять память и под набор объектов. Например, выделим память для массива из 4-х чисел int:
#include #include int main(void) < int n = 4; int *ptr = malloc(n * sizeof(int)); // выделяем память для 4-х чисел int if(ptr) < // помещаем значения в выделенную память ptr[0] = 1; ptr[1] = 2; ptr[2] = 3; ptr[3] = 5; // получаем значения for(int i = 0; i < n; i++) < printf("%d", ptr[i]); >> free(ptr); >
Выделение памяти для структуры
Аналогичным образом можно выделять память для одной или набора структур:
#include #include struct person < char* name; int age; >; int main(void) < // выделяем память для одной структуры person struct person *ptr = malloc(sizeof(struct person)); if(ptr) < // помещаем значения в выделенную память ptr->name = "Tom"; ptr->age = 38; // получаем значения printf("%s : %d", ptr->name, ptr->age); // Tom : 38 > free(ptr); return 0; >
calloc
Функция calloc() имеет прототип
void *calloc(unsigned n, unsigned m);
Она выделяет память для n элементов по m байт каждый и возвращает указатель на начало выделенной памяти. В случае неудачного выполнения возвращает NULL
В отличие от функции malloc() она инициализирует все выделенные байты памяти нулями. Например, выделим память для одного объекта int :
#include #include int main(void) < // выделяем память для одного объекта int int *ptr = calloc(1, sizeof(int)); if(ptr) < // получаем значение по умолчанию - 0 printf("Initial value: %d", *ptr); // Initial value: 0 // устанавливаем новое значение *ptr = 15; // получаем новое значение printf("New value: %d", *ptr); // New value: 15 >free(ptr); return 0; >
Initial value: 0 New value: 15
Подобным образом можно выделить память и для других объектов. Например, выделим память для массива из 4-х объектов int :
#include #include int main(void) < // выделяем память для 4-х объектов int int n = 4; int *ptr = calloc(n, sizeof(int)); if(ptr) < // устанавливаем значения ptr[0] = 1; ptr[1] = 2; ptr[2] = 3; ptr[3] = 5; // получаем значения for(int i = 0; i < n; i++) < printf("%d", ptr[i]); >> free(ptr); >
realloc
Функция realloc() позволяет изменить размер памяти, ранее выделенной с помощью функций malloc() b calloc() . Имеет прототип
void *realloc(void *bl, unsigned ns);
Первый параметр представляет указатель на ранее выделенный блок памяти. А второй параметр представляет новый размер блока памяти в байтах.
Если указатель bl имеет значение NULL , то есть память не выделялась, то действие функции аналогично действию malloc
Рассмотрим небольшой пример:
#include #include int main(void) < // выделяем память для 1-го объекта int int size = sizeof(int); int *ptr = malloc(size); if(ptr) < // отображаем адрес и размер памяти printf("Addresss: %p \t Size: %d\n", (void*)ptr, size); >// расширяем память до размера 4-х объектов int size = 4 * sizeof(int); int *ptr_new = realloc(ptr, size); // если выделение памяти прошло успещно if(ptr_new) < printf("Reallocation\n"); // заново отображаем адрес и размер памяти printf("Addresss: %p \t Size: %d\n", (void*)ptr_new, size); free(ptr_new); // освобождаем новый указатель >else < free(ptr); // освобождаем старый указатель >>
Здесь сначала выделяем память для одного объекта int с помощью функции malloc.
int size = sizeof(int); int *ptr = malloc(size);
Если память успешно выделена, то выводим на консоль адрес и размер выделенного блока памяти. Затем с помощью функции realloc расширяем память до 4 объектов int
size = 4 * sizeof(int); int *ptr_new = realloc(ptr, size);
Если увеличение памяти прошло успешно, то заново выводим данные на консоль и освобождаем память по новому указателю. Если увеличение памяти прошло не удачно, то освобождаем память но старому указателю.
Консольный вывод в моем случае
Addresss: 0000018B078A82F0 Allocated: 4 Reallocation Addresss: 0000018B078A82F0 Allocated: 16
Стоит отметить, что нам необязательно создавать новый указатель, мы можем присвоить значение старому указателю:
#include #include int main(void) < int size = sizeof(int); int *ptr = malloc(size); if(ptr) < printf("Addresss: %p \t Allocated: %d\n", (void*)ptr, size); >size = 4 * sizeof(int); ptr = realloc(ptr, size); // используем старый указатель if(ptr) < printf("Reallocation\n"); printf("Addresss: %p \t Allocated: %d\n", (void*)ptr, size); >free(ptr); >
Быстрое создание многомерных динамических массивов
В этом примере сначала выделяется память под массив указателей, потом M раз выделяется память под массивы. Во время удаления массива сначала M раз удаляются массивы, а потом удаляется массив указателей. Операции malloc и free затратные. Кроме того, выделение маленьких кусков памяти приводит к фрагментации памяти, так что последующее выделение памяти становится ещё медленнее.
Розовым обозначен массив указателей
Массив — это непрерывная последовательность байт. Массив не хранит своего размера. Указатель на массив хранит всего лишь адрес начала массива. Поэтому можно существенно ускорить выделение и освобождение памяти под массив. Выделяем сначала память под массив указателей, а затем первому элементу выделяем память под все массивы одновременно. Таким образом, первый элемент будет хранить адрес начала этого массива. С его помощью «делим» массив, раздавая его оставшимся указателям.
const int M = 100; const int N = 200; int **a = NULL; int i; a = (int**) malloc(M * sizeof(int*)); a[0] = (int*) malloc(M * N * sizeof(int)); for (i = 1; i < M; i++) < a[i] = a[0] + i * N; >//Важные действия free(a[0]); free(a);
Теперь нам необходимо всего две операции выделения памяти и две операции для освобождения.
Розовым обозначен массив указателей
У этого подхода есть и ещё одно важное преимущество. Массив a[0] по структуре становится похож на одномерный, так что его можно передавать как одномерный, например, для сортировки. Элементы расположены в нём по рядам, как в двумерном статическом массиве, поэтому без проблем можно его привести к типу указателя на массивы.
Можно пойти ещё дальше и заменить всё одним вызовом malloc: упаковать друг за другом сначала массив указателей, а потом массив массивов.
const int M = 100; const int N = 200; int **a = NULL; int i, j; a = (int**) malloc(M * sizeof(int*) + N * M * sizeof(int)); a[0] = (int*)(a + M); for (i = 1; i < M; i++) < a[i] = a[0] + i * N; >//Важные действия free(a);
Здесь всего одна операция выделения и одна освобождения.
Розовым обозначен массив указателей
Для массивов более высокой размерности выделение памяти остаётся очень похожим.
Скорость выполнения соотносится для данных способов выделения памяти как 404:13:12 для массива размером 100 x 200 типа int. Последние два способа выделения памяти, дабы не смущать неокрепшие умы, почти не используются в курсе, но на практике динамически выделять память под многомерные массивы лучше именно таким образом.
Рассмотрим выделение памяти под трёхмерный массив. Трёхмерный массив — массив указателей на указатели, которые ссылаются на массивы указателей, которые ссылаются на массивы объектов заданного типа. Выделение памяти под трёхмерный массив размером M*N*K, соответственно, потребует M + M*N операций выделения памяти и столько же для освобождения.
Серым обозначен массив указателей на указатели, розовым массив указателей
Первым делом объявим переменные
const int M = 10; const int N = 10; const int K = 10; int*** a = NULL; int* data; int** ptrs; int i, j, k;
Здесь a — наш будущий трёхмерный массив, data — вспомогательная переменная, которая хранит адрес, по которому начинаются непосредственно данные (белым цветом на рисунке). ptrs — вспомогательная переменная, которая хранит адрес, по которому начинаются массивы указателей (розовый на рисунке).
Для начала выделим память под массив
a = (int***) malloc(M * sizeof(int**) + M*N * sizeof(int*) + M*N*K * sizeof(int));
Затем инициализируем вспомогательные переменные
ptrs = (int**) (a + M); data = (int*) (a + M + M*N);
Затем надо инициализировать массив указателей на указатели
for (i = 0; i
Но также нужно инициализировать каждый из массивов указателей
for (i = 0; i < M; i++) < a[i] = ptrs + i*N; for (j = 0; j < N; j++) < a[i][j] = data + j * N*K; >>
Теперь наш массив принимает вид:
Серым обозначен массив указателей на указатели, розовым массив указателей
const int M = 10; const int N = 10; const int K = 10; int*** a = NULL; int* data; int** ptrs; int i, j, k, q; a = (int***) malloc(M * sizeof(int**) + M*N * sizeof(int*) + M*N*K * sizeof(int)); ptrs = (int**) (a + M); data = (int*) (a + M + M*N); q = 0; for (i = 0; i < M; i++) < a[i] = ptrs + i*N; for (j = 0; j < N; j++) < a[i][j] = data + (q++) * N*K; >>
ru-Cyrl 18- tutorial Sypachev S.S. 1989-04-14 sypachev_s_s@mail.ru Stepan Sypachev students
Всё ещё не понятно? – пиши вопросы на ящик
О динамических массивах в языке Си: что это такое, виды, как с ними работать
Массив — последовательная группа ячеек памяти, имеющих одинаковое имя и одинаковый тип. То есть это структуры, которые содержат связанные друг с другом однотипные элементы данных.
Они занимают область в памяти. Компилятор резервирует соответствующий объем памяти для каждого типа и количества элементов каждого массива.
Чтобы зарезервировать память при помощи компилятора для статического массива, необходимо указать ему сколько в нем будет элементов целых чисел. Для этого используется объявление int a [] ;
Осторожно! Если преподаватель обнаружит плагиат в работе, не избежать крупных проблем (вплоть до отчисления). Если нет возможности написать самому, закажите тут.
Пример объявления для 12 элементов:
Для динамического массива количество элементов не указывают.
На этапе написания программы размер динамических массивов неизвестен. Ввод количества элементов осуществляется во время работы программы.
Размером при объявлении динамического массива является числовая переменная, а не константа.
Передача динамических массивов в функцию осуществляют через указание на начало массива указателей. То есть объявляют тип указателя, содержащего данные об адресе соответствующего первого элемента массива.
В динамических массивах также не указывают длину строк и их количество. Границы массивов полностью контролируются разработчиком.
Указатели для динамических массивов
Одним из основных понятий языка Си являются указатели. Они представляют собой переменные, хранящие информацию об адресе какого-либо объекта. Их особенностью является то, что иногда только с их помощью можно выполнить некоторые операции, или записать код более компактно и эффективно, чем при использовании других способов.
В такие переменные чаще всего записывают адрес начального элемента динамического массива, однако возможность записи адресов любых участков памяти также существует.
Действия с указателями
Указатели:
- int *pI;
- char *pC;
- float *pF;
Чтобы объявить указатель, объявляют тип переменной и ставят перед именем символ *. Указанная переменная должна быть одного типа с указателем, который на ее указывает.
Указатели:
Адрес присваивается указателю с помощью оператора &. Знак &, стоящий перед переменной, будет указывать на ее адрес.
- Получение значения по этому адресу.
Указатели:
- f = *pF;
- float f, *pF;
Для переменной определенного типа, на которую определен указатель, например, pF, указывается число соответствующего типа. Символ * перед pF означает информацию ячейки, указанной pF.
Указатели:
Подобные операции позволяют сдвигать значение указателя на то или иное целое число или количество байтов.
Указатели:
Указатель указывает на недействительный адрес, который равен нулю, соответственно, указатель тоже недействительный. Запись по нему не может быть осуществлена.
Указатели:
- int i, *pI;
- printf(«Адр.i =%p», pI);
- pI = &i;
Для вывода указателей на экран применяют формат %p.
Ошибки, возникающие при неверном использовании динамических массивов
- Запись в чужую область памяти.
Причина: Выделение памяти произошло неудачно, при этом массив используется.
Вывод: необходимо всегда осуществлять проверку указателя на NULL. Если значение указателя будет равно нулю при проверке после выделения памяти, то использование такого массива будет приводить к зависанию компьютера.
Причина: Массив уже удален и теперь удаляется снова.
Вывод: если массив удален из памяти, необходимо обнулить показатель, так можно быстрее выявить ошибку.
Причина: В массив записан элемент с отрицательным индексом или индексом, выходящим за границу массива.
Причина: Неиспользуемая память не освобождается. Если это происходит в функции, которая вызывается много раз, то ресурсы памяти скоро будут израсходованы. Вывод: необходимо тщательно проверить код, и удалить артефакты.
Виды динамических массивов
Классификация динамических массивов:
- одномерные: int * A;
- двумерные: int ** A;
Одномерный динамический массив представляет собой множество элементов одного типа данных.
Двухмерный массив имеет более сложную структуру и содержит в качестве элементов массива другие массивы. Каждому хранящемуся в массиве А указателю присвоено не одно значение, а одномерный динамический массив таких значений.
Переменная А сама является указателем и объявляется как указатель на указатель на нужный тип. Данный указатель нужно инициализировать, то есть положить ему адрес массива адресов. В памяти программы должен существовать массив адресов указателей на int и сам массив указателей на int. В этом массиве указателей должны быть разложены адреса, возможно лежащие отдельно друг от друга в памяти.
Пример двумерного массива:
- #include // здесь указывают заголовок файла, содержащего функции, переменные, классы, для организации операций ввода-вывода
- using namespace std; // объявление пространства имен для ограничения видимости переменных, функций и т.д.
- int main()
- setlocale(0, «»); “// указывают тип значения, возвращаемого функцией, и задают локаль для программы
- int **dinamic_array2 = new int* [5];
- for (int i = 0; i < 5; i++)
- dinamic_array2[i] = new int [i + 1];
- > // Создание двумерного массива
- for (int i = 0; i < 5; i++)
- cout
- for (int j = 0; j < i + 1; j++)
- cin >> dinamic_array2[i][j];
- >
- > // заполнение массива
- for (int j = 0; j < i + 1; j++)
- sum += dinamic_array2[i][j];
- >
- cout
- > // проведение различных операций по вводу-выводу
- for (int i = 0; i < 5; i++)
- delete [] dinamic_array2[i]; // удаление массива
- >
- system(«pause»);
- return 0;
- >
Строки 5-8 — создание динамического массива.
Строки 9-14 — заполнение.
Строки 15-19 — подсчет, сортировка и вывод на экран суммы всех массивов.
Строки 20-22 — удаление массива.
Стандартные функции динамического выделения памяти
В языке программирования Си имеются стандартные функции управления памятью:
- Malloc (от англ. memory allocation, выделение памяти). Функция malloc возвращает указатель на n байт неинициализированной памяти или NULL, если запрос на память нельзя выполнить: void *malloc(size_t n). Значение, которое возвращает malloc, — это адрес начала выделенной области памяти. При этом гарантируется соответствующее выравнивание этого адреса на границу памяти, обеспечивающую хранение в области любого объекта.
- Calloc (от англ. clear allocation, чистое выделение памяти). Функция calloc возвращает указатель на участок памяти, достаточный для размещения п объектов заданного размера size или NULL, если запрос на память невыполним. Память инициализируется нулями; void *calloc(size_t n, size_t size).
- Realloc (от англ. reallocation, перераспределение памяти). Используется для изменения величины выделенной памяти, на которую указывает ptr, на новую величину, задаваемую параметром newsize. Эта функция может перемещать блок памяти на новое место, в этом случае функция возвращает указатель на новое место в памяти.
- Free (англ. free, освободить). Функция free(p) освобождает участок памяти, на который указывает указатель р, первоначально полученный вызовом функции malloc или calloc. Порядок освобождения выделенных участков памяти не регламентируется. Однако если указатель не был получен с помощью malloc или calloc, то его освобождение является грубой ошибкой. Обращение по указателю после его освобождения — также ошибка. Правильным было бы записать все, что нужно, перед освобождением:
for (p = head; p != NULL; p = q)
Выделение памяти под двумерный массив
Для того, чтобы создать двумерный массив, необходимо осуществить множественные системные вызовы по выделению памяти.
Например, есть указатель А: int ** A ;
Сначала создают массив, состоящий из указателей, которые будут отвечать количеству строк:
A = (int **) malloc (N * sizeof(int *)). Здесь важно указать тип указателя, а не int. Потому что в этом массиве, на который указывает A, будут храниться указатели, а не int.
Далее инициализируют уже сами элементы этого массива указателей путем запуска цикла:
for (int i = 0 ; i < N ; ++i).
Для каждого A[i] проводим инициализацию по отдельности. По сути этого разыменование А со смещением i:
A[i] = (int *) malloc (M * sizeof (int)). Указатели A[i] уже указывают на массив int. Если бы был другой тип, то указывали бы на него.
Для освобождения памяти используют схему: сначала освобождают память для указателей, а потом уже для самого указателя A. То есть массив, который выделил массив указателей, тоже сбрасывают.
A = (int **) malloc (N * sizeof(int *)).
for (int i = 0 ; i < N ; ++i).
Нестандартные функции динамического выделения памяти
Когда требуемый размер массива становится известен, то используют оператор new из языка Си ++, который является расширенной версией языка Си. В скобках указывают размер массива:
При отрицательном или нулевом N использовать оператор new нельзя.
При динамическом распределении памяти основными операциями являются new и delete.
Операция new принимает в качестве аргумента тип динамически размещаемого объекта и возвращает на него указатель.
Например, оператор Node *newPtr = new NodeA0); используется для выделения области памяти размером sizeof(Node) байтов, а также его применяют для сохранения указателя на данной области памяти в указателе newPtr.
Если планируется использовать память повторно, после того, как динамический массив в какой-то момент работы программы перестанет быть нужным, то ее освобождают с помощью delete[],
При этом не указывают размерность массива. Операция delete освобождает область памяти, выделенную при помощи оператора new. Таким образом, она возвращает системе эту область памяти для дальнейшего распределения. Чтобы освободить память, которая была динамически выделена предыдущим оператором, применяют оператор delete newPtr;
Иногда выделение памяти под динамические массивы осуществляют с помощью двух языков Си и Си++ одновременно: операции new и функции malloc.
int *a = new int[n];
double *b = (double *)malloc(n * sizeof (double));
Во второй строке описан указатель на целую величину. Ему присвоен адрес начала непрерывной области динамической памяти, выделенной с помощью операции new. В зависимости от того, сколько присутствует n величин типа int, столько выделяется памяти для их хранения. Величина n может являться переменной.
В третьей строке применяется функция malloc, которая в данном случае выделяет память под n элементов типа double. Для того, чтобы освободить память, выделенную с помощью функции malloc, применяют функцию free. Память не обнуляется при ее выделении. Динамический массив нельзя инициировать.
Перераспределение памяти
Динамическое перераспределение памяти позволяет создавать и поддерживать динамические структуры данных. Оно дает возможность осуществлять увеличение области памяти в процессе выполнения программы, для того чтобы хранить новые узлы и освобождать ресурсы памяти, в которых уже нет необходимости.
Объем доступной физической памяти или доступной виртуальной памяти в системах с виртуальной памятью определяют пределы динамического выделения памяти. При делении свободной памяти при совместном доступе между многими пользователями эти пределы несколько снижены.
Функция realloc осуществляет перераспределение памяти. Она меняет размер динамически выделяемой области памяти, адресуемой указателем ptr, на новый размер size.
Realloc может возвращать адрес новой области памяти:
realloc(void *ptr, size_t size);
Если ptr равен NULL, то realloc ведет себя подобно функции malloc.
Поведение функции realloc будет неопределенным, если:
- значение ptr не было возвращено функциями calloc, malloc или realloc;
- пространство памяти было освобождено функцией free, и ptr указывают на него.
Size указывают в абсолютном значении.
Важные моменты в перераспределении памяти с помощью функции realloc:
- Если существующее пространство меньше по размеру, чем size, то в конце будет выделяться новое неинициализированное непрерывное пространство, при этом предыдущие данные пространства будут сохранены.
- Значение, равное NULL, будет возвращено, если realloc не может выделить запрашиваемое пространство, а в указанном ptr пространстве содержимое остается нетронутым.
- Realloc будет действовать, как функция free, если size=0, а ptr не равен NULL.
- Если первым параметром функции realloc использовать NULL, то можно получить эффект, который достигается с помощью функции malloc с тем же значением size.
Новое пространство может начинаться с отличного от заданного адреса, независимо от того, в какой момент функция realloc изменяла пространство, даже если она усекала память. Поэтому указатели могут адресоваться к перемещаемому пространству, что необходимо учитывать при разработке программы.
Например, при создании связанного списка linked list и применения realloc, чтобы выделить для цепочки пространство памяти, может оказаться, что оно будет перемещаться. В таком случае, указатели будут адресованы не в место их расположения в настоящий момент, а в то место, где были размещены последовательные звенья цепочки.
Пример использования функции realloc:
p2 = realloc(p1, new_size);
if (p2 1= NULL) p1 = p2;
Необходимо учитывать, что realloc работает с ранее выделенной памятью и старыми строками. Добавление новых строк и выделение памяти осуществляется посредством функций calloc или malloc.
Динамический массив в С++
Динамическое выделение памяти необходимо для эффективного использования памяти компьютера. Например, мы написали какую-то программку, которая обрабатывает массив. При написании данной программы необходимо было объявить массив, то есть задать ему фиксированный размер (к примеру, от 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 using namespace std; int main(int argc, char* argv[]) < int *ptrvalue = new int; // динамическое выделение памяти под объект типа int *ptrvalue = 9; // инициализация объекта через указатель //int *ptrvalue = new int (9); инициализация может выполнятся сразу при объявлении динамического объекта cout