Здесь показаны различия между двумя версиями данной страницы.
— |
operatory_dinamicheskogo_raspredelenija_pamjati [2018/12/30 02:33] (текущий) |
||
---|---|---|---|
Строка 1: | Строка 1: | ||
+ | ====== Операторы динамического распределения памяти С++ ====== | ||
+ | {{htmlmetatags> | ||
+ | metatag-description=(В языке С++ предусмотрены два оператора динамического распределения памяти: new и delete.) | ||
+ | }} | ||
+ | {{ ::cpp-memory-01.png?nolink&400 |}} | ||
+ | **Операторы динамического распределения памяти**: new(), delete(); malloc(), free(). | ||
+ | В языке С++ предусмотрены два оператора динамического распределения памяти: **new** и **delete**. Эти операторы выделяют и освобождают память в ходе выполнения программы. Динамическое распределение памяти представляет собой важную часть практически всех реальных программ. В языке С++ есть альтернативный способ динамического распределения памяти, основанный на функциях malloc() и free(). Они сохранены для того, чтобы достичь совместимости с языком С. Однако в программах на языке С++ следует применять операторы new и delete, поскольку они имеют ряд важных преимуществ: во-первых, оператор new автоматически выделяет количество памяти, необходимое объекту указанного типа (оператор [[sizeof]] теперь применять не следует), во-вторых, оператор new автоматически возвращает указатель заданного типа. Также операторы new и delete можно перегружать, что позволяет создавать настраиваемые системы для выделения динамической памяти. <note tip>Оператор delete следует применять только к результатам оператора new. В противном случае могут возникнуть проблемы, например, крах операционной системы.</note> | ||
+ | ===== Общее определение операторов new и delete ===== | ||
+ | Оператор new выделяет область памяти и возвращает указатель на ее первую ячейку. Оператор delete освобождает память, выделенную ранее с помощью оператора new. | ||
+ | |||
+ | * //указатель// = **new** //тип// (//начальное_значение//); | ||
+ | * **delete** //указатель// | ||
+ | * в случае массива в оператор delete используются скобки []: **delete** [] //указатель// | ||
+ | <file> | ||
+ | /* | ||
+ | * File: | ||
+ | * Author: darkfire | ||
+ | * | ||
+ | * Created on September 15, 2010, 6:32 PM | ||
+ | */ | ||
+ | |||
+ | #include <iostream> | ||
+ | #include <ctime> | ||
+ | #include <stdlib.h> | ||
+ | |||
+ | using namespace std; | ||
+ | |||
+ | const int SIZE = 7; | ||
+ | |||
+ | int main () { | ||
+ | srand(time(NULL)); | ||
+ | int *parr = new int [SIZE]; // Определили указатель. Выделили память для массива. | ||
+ | int *parr0 = parr; //сохранили для дальнейшего использования адресс массива. | ||
+ | |||
+ | for (int i=0;i<SIZE-1;i++){ | ||
+ | *parr=rand()%100; | ||
+ | cout<<*parr<<"\n"; | ||
+ | parr++; | ||
+ | } | ||
+ | parr = parr0; | ||
+ | | ||
+ | for (int i=0;i<SIZE-1;i++){ | ||
+ | cout<<*parr<<"\n"; | ||
+ | parr++; | ||
+ | } | ||
+ | parr = parr0;/* если указателю не присвоить адресс первого элемента массива | ||
+ | * оператор делете будет выводить ошибку. | ||
+ | */ | ||
+ | delete [] parr; | ||
+ | |||
+ | } | ||
+ | </file> | ||
+ | ====== Многомерные динамические массивы ====== | ||
+ | Многомерный массив в C по своей сути одномерен. Операции new и delete позволяют создавать и удалять динамические массивы, поддерживая при этом иллюзию произвольной размерности. Деятельность по организации динамического массива требует дополнительного внимания, которое окупается важным преимуществом: характеристики массива (операнды операции new) могут не быть константными выражениями. Это позволяет создавать многомерные динамические массивы произвольной конфигурации. | ||
+ | |||
+ | Следующий пример иллюстрирует работу с динамическими массивами. | ||
+ | <file> | ||
+ | #include <iostream> | ||
+ | using namespace std; | ||
+ | |||
+ | void main() | ||
+ | { | ||
+ | int i, j; | ||
+ | |||
+ | // Переменные для описания характеристик массивов. | ||
+ | int m1 = 5, m2 = 5; | ||
+ | |||
+ | /* | ||
+ | Организация двумерного динамического массива производится в два этапа. | ||
+ | Сначала создаётся одномерный массив указателей, а затем каждому элементу | ||
+ | этого массива присваивается адрес одномерного массива. Для характеристик | ||
+ | размеров массивов не требуется константных выражений. | ||
+ | */ | ||
+ | int **pArr = new int*[m1]; | ||
+ | for (i = 0; i < m1; i++) | ||
+ | pArr[i] = new int[m2]; | ||
+ | |||
+ | pArr[3][3] = 100; | ||
+ | cout << pArr[3][3] << "\n"; | ||
+ | |||
+ | //Последовательное уничтожение двумерного массива… | ||
+ | |||
+ | for (i = 0; i < m1; i++) | ||
+ | delete[]pArr[i]; | ||
+ | delete[]pArr; | ||
+ | } | ||
+ | </file> | ||
+ | |||
+ | ====== Алгоритм изменения размера динамического массива ====== | ||
+ | Например, мы хотим увеличить размер уже существующего динамического массива на 1. | ||
+ | - Создаем новый динамический массив с размерность на единицу больше от существующего массива. | ||
+ | - Копируем все данные из старого массива в новый массив. | ||
+ | - Добавляем значение нового элемента массива. | ||
+ | - Удаляем старый массив. (Может понадобиться изменить переменную размерности массива, например если размерность указывалась через глобальную переменную). | ||
+ | - Присваиваем старому указателю адрес нового массива. | ||
+ | |||
+ | ====== Примеры на многомерные динамические массивы ====== | ||
+ | * Организация двумерного "треугольного" динамического массива. | ||
+ | Сначала создаётся одномерный массив указателей, а затем каждому элементу этого массива присваивается адрес одномерного массива. При этом размер (количество элементов) каждого нового массива на единицу меньше размера предыдущего. Включённая в квадратные скобки переменная, которая является операндом операции new, позволяет легко сделать это. | ||
+ | |||
+ | <file> | ||
+ | #include <iostream> | ||
+ | using namespace std; | ||
+ | |||
+ | void main() | ||
+ | { | ||
+ | int i, j; | ||
+ | |||
+ | // Переменные для описания характеристик массивов. | ||
+ | int m1 = 5, wm = 5; | ||
+ | int **pXArr = new int*[m1]; | ||
+ | |||
+ | for (i = 0; i < m1; i++, wm--) | ||
+ | pXArr[i] = new int[m1]; | ||
+ | |||
+ | |||
+ | //Заполнение массива нулями и показ его на экран | ||
+ | for (i = m1 - 1; i >= 0; i--, wm++) { | ||
+ | for (j = 0; j < wm; j++){ | ||
+ | pXArr[i][j]=0; | ||
+ | cout<<pXArr[i][j]<<"\t"; | ||
+ | } | ||
+ | cout<<"\n\n"; | ||
+ | } | ||
+ | |||
+ | //Последовательное уничтожение двумерного массива треугольной конфигурации… | ||
+ | |||
+ | for (i = 0; i < m1; i++) | ||
+ | delete[]pXArr[i]; | ||
+ | delete[]pXArr; | ||
+ | } | ||
+ | </file> | ||
+ | |||
+ | * **Организация трехмерного динамического массива.** | ||
+ | Создание и уничтожение трёхмерного массива требует дополнительной итерации. Однако здесь также нет ничего принципиально нового. | ||
+ | <file> | ||
+ | #include <iostream> | ||
+ | using namespace std; | ||
+ | |||
+ | void main() | ||
+ | { | ||
+ | int i, j; | ||
+ | |||
+ | // Переменные для описания характеристик массивов. | ||
+ | int m1 = 5, m2 = 5, m3 = 2; | ||
+ | |||
+ | // указатель на указатель на указатель :) | ||
+ | int ***ppArr; | ||
+ | |||
+ | // Создание массива | ||
+ | ppArr = new int**[m1]; | ||
+ | for (i = 0; i <m1; i++) | ||
+ | ppArr[i] = new int*[m2]; | ||
+ | |||
+ | for (i = 0; i < m1; i++) | ||
+ | for (j = 0; j < m2; j++) | ||
+ | ppArr[i][j] = new int[m3]; | ||
+ | |||
+ | ppArr[1][2][3] = 750; | ||
+ | cout << ppArr[1][2][3] << "\n"; | ||
+ | |||
+ | // Удаление в последовательности, обратной созданию | ||
+ | for (i = 0; i < m1; i++) | ||
+ | for (j = 0; j < m2; j++) | ||
+ | delete[]ppArr[i][j]; | ||
+ | |||
+ | for (i = 0; i < m1; i++) | ||
+ | delete[]ppArr[i]; | ||
+ | delete[] ppArr; | ||
+ | } | ||
+ | </file> |