Лекция 9
Динамическое распределение памяти в языке С++
Различают статическое и динамическое распределение памяти компьютера под объекты.
Статическое распределение предполагает, что память для размещения объектов выделяется в процессе компиляции программ. Иначе говоря, компилятор создает объекты, выделяя для них память на основании соответствующих определений.
Например, определение переменной int array[10]; свидетельствует о том, что в программе вводится массив, который требует память для размещения десяти элементов целого типа. Компилятор каждому имени объекта ставит в соответствие адрес. В связи с этим, доступ к статическим объектам реализуется по именам.
Компилятор не может выделять память под объекты с динамической структурой данных, поскольку их структура, а ,следовательно, и объем памяти могут меняться в процессе выполнения программы. Память под такие объекты выделяется на этапе выполнения программы. Поскольку на этапе компиляции программы адреса динамических объектов не известны , то доступ к ним организуется не по именам, а через указатели.
Каждой программе компьютер выделяет память, состоящую из четырех секций:
1. программная секция, включающая код программы;
2. секция данных, содержащая внутренние представления статических объектов;
3. стек – область памяти, используемая при реализации функций;
4. динамическая память (ДП), предоставляемая программе при ее выполнении.
Создание динамического объекта осуществляется в два этапа
1 этап. Резервирование места в ДП под объект и формирование значения указателя, ссылающегося на это объект.
2 этап. Запись значения объекта в ДП по указанному адресу.
Для выделения ДП под объект служит оператор new.
Синтаксис этого оператора:
<имя указателя>=new <тип >;
Оператор new выделяет в ДП место под значение заданного типа и возвращает адрес этой области. Например:
float *p;
p=new float;
После того, как указатель приобрел конкретное значение, по этому адресу можно разместить значение соответствующего типа. Например:
*p=15.46;
Для освобождения ДП используется оператор delete:
delete <имя указателя>;
Оператор delete освобождает память, ранее связанную с указателем. Например:
delete p;
В операторе delete необходимо использовать только тот указатель, который был определен в операторе new.
При использовании оператора new можно инициализировать значение объекта:
<имя указателя>= new <тип>(<инициализатор>);
Здесь тип инициализатора должен быть совместимым с типом объекта, для которого выделяется память.
Например:
void main()
{ int *p;
p=new int(250);
cout<< *p<<”\n”;
delete p;
}
С помощью оператора new можно выделять память под массивы:
<имя указателя>= new <тип элемента массива>[<размер>];
Здесь <размер>- количество элементов в массиве.
Для освобождения ДП, выделенной под массив, можно использовать оператор delete следующего формата:
delete []<имя указателя>;
Пример. Создать в ДП массив из 10 целых чисел, вывести его на экран и освободить ДП.
void main()
{ int *p, i;
p=new int[10];
for( i=0; i<10; i++)
p[i]=i;
for( i=0; i<10; i++)
cout<< p[i]<<” “;
cout<<”\n”;
delete[] p;
}
Используя операторы new и delete можно выделять ДП под экземпляры классов и освобождать ее.
При размещении объекта в ДП с помощью оператора new вызывается конструктор, а при освобождении ДП вызывается деструктор.
Пример. Разместить объект класса “прямоугольник” в ДП, вычислить площадь прямоугольника и освободить ДП.
#include <iostream.h>
class Rectangle
{ int width, height;
public:
Rectangle(int w, int h)//конструктор
{width=w; height=h;
cout<<”Создание прямоугольника.\n”;
}
~ Rectangle()//деструктор
{cout<<”Разрушение прямоугольника.\n”;
}
int area()
{return width * height;
}
};
void main()
{ Rectangle *p;
p= new Rectangle(10,8);
cout<<”Площадь=”<<p->area()<<”.\n”;
delete p;//вызов деструктора
}
Результат:
Cоздание прямоугольника.
Площадь=80.
Разрушение прямоугольника.
Динамические структуры данных
ДП широко используется для хранения динамических структур данных (ДСД). К ДСД относят списки, стеки, очереди и деревья.
Рассмотрим списки. Различают линейные и циклические, однонаправленные и двунаправленные, упорядоченные и неупорядоченные списки.
Линейный однонаправленный список (ЛОС)
ЛОС – это ДСД, каждый элемент которой включает информационное поле и указатель на следующий элемент. Поле указателя последнего элемента ЛОС имеет значение NULL (пустой указатель). Информационное поле содержит ключ, идентифицирующий элемент, и ,возможно любую другую информацию.
На языке С++ элемент ЛОС можно описать в виде класса.
Например:
class list
{public:
char name[80];//имя
int year;//год рождения
list *next;//указатель на следующий элемент списка
void create();//создание списка
void output();//вывод на экран элементов списка
};