Лекция 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();//вывод на экран элементов списка

};