
- •1.Фундаментальные типы данных. Структуры
- •Демонстрационный пример
- •1.2. Задачи для самостоятельного решения
- •Фундаментальные типы данных. Объединения
- •2.1. Демонстрационный пример
- •А.Пуанкаре Приведем пример использования объединения: составить программу, выполняющую требуемые операции для заданной фигуры.
- •2.2. Задачи для самостоятельного решения
- •3.Ссылочные типы
- •3.1. Указатели и адреса
- •3.2. Адресная арифметика
- •3.3. Операции new и delete
- •3.4. Демонстрационные примеры Чтение и переработка являются ключевыми в программировании. Б.Керниган, ф.Плоджер
- •3.5. Задачи для самостоятельного решения
- •3.4. Дано описание переменных: int *p,*q; char *r;. Какие из следующих операторов неправильны и почему?
- •4. Линейные однонаправленные списки
- •4.1. Задачи для самостоятельного решения
- •Г.Остер. Задачник
- •Построение
- •Модификация
- •Предикаты
- •Подсчет
- •5. Ортогональные списочные структуры ("гирлянды" и "висюльки")
- •5.1. Фрагмент теории
- •5.2. Задачи для самостоятельного решения
- •6. Кольцевые списки на базе однонаправленных списков
- •6.1. Фрагмент теории
- •6.2.Задачи для самостоятельного решения
3.3. Операции new и delete
Я тебя породил, я тебя и убью!
Н.В.Гоголь. Тарас Бульба
Операции:
<указатель> = new <имя типа>
либо
<указатель> = new <имя типа>( <инициализатор>)
позволяют выделить и сделать доступным свободный участок в основной памяти, размеры которого соответствуют типу данных, определяемому именем типа. В выделенный участок заносится значение, определяемое инициализатором, который не является обязательным элементом. В случае успешного выполнения операция new возвращает адрес начала выделенного участка памяти. Если участок нужных размеров не может быть выделен (нет памяти), то операция new возвращает нулевое значение адреса (NULL).
Здесь необязательный инициализатор - это выражение в круглых скобках, значением которого заполняется выделенная область памяти. Указатель, которому присваивается получаемое значение адреса, должен относиться к тому же типу данных, что и имя_типа в операции new. Примеры:
операция new float выделяет участок памяти размером 4 байта;
операция new int(l5) выделяет участок памяти в 2 байта и инициализирует этот участок целым значением 15.
Напомним, что определение указателя имеет вид: тип *<имя указателя>; . Имя указателя - это идентификатор. Таким образом, int *h; - определение указателя h, который может быть связан с участком памяти, выделенным для величины целого типа. Введя с помощью определения указатель, можно присвоить ему возвращаемое операцией new значение:
h = new int(15); .
В дальнейшем доступ к выделенному участку памяти обеспечивает выражение *h.
В случае отсутствия в операции new инициализатора значение, которое заносится в выделенный участок памяти, не определено. Если в качестве имени типа в операции new используется массив, то для массива должны быть полностью определены все размерности. Инициализация участка памяти, выделяемого для массива, запрещена.
Продолжительность существования, выделенного с помощью операции new участка памяти - от точки создания до конца программы или до явного его освобождения.
Для явного освобождения, выделенного операцией new участка памяти, используется оператор delete, общий вид которого следующий:
delete <указатель>; , где
указатель адресует освобождаемый участок памяти, ранее выделенный с помощью операции new. Например: delete h; освободит участок памяти, связанный с указателем h. Повторное применение операции delete к тому же указателю дает неопределенный результат.
Для освобождения памяти, выделенной для массива, используется следующая модификация того же оператора: delete[ ] <указатель>;, где указатель связан с выделенным для массива участком памяти.
3.4. Демонстрационные примеры Чтение и переработка являются ключевыми в программировании. Б.Керниган, ф.Плоджер
Приведем несколько примеров, иллюстрирующих применение указателей.
Пример 1. Инициализация вещественного "массива" размерностью 32000 элементов.
#include<iostream.h>
void main ()
{
// float x[32000]; Наличие этого описания приведет к ...
//Выделение места для массива и размещение адреса начала
//массива в переменной g.
float *g=new float [32000];
for (int i=0; i<32000; i++)
{ *(g+i) = i;
cout<<*(g+i)<<" ";
}
delete[] g;//Возврат памяти в "кучу".
}
Пример 2. Использование указателей для работы со списками.
Создадим сначала две динамические переменные:
R = new CT; Q = new CT;
А теперь построим список, содержащий два звена:
(*R).I = 15; (*Q).I = 20;
(*R).P = Q;
(*Q).P = NULL;
Результат:
Создадим еще один список: R1 = new CT; Q1 = new CT;
(*R1).I = 13;
(
*Q1).I
= 53;
(*R1).P = Q1;
(*Q1).P = NULL;
Р
езультат:
Проиллюстрируем теперь схематически результат действия оператора присваивания:
(*R1).P = (*R).P;
#include<iostream.h>
typedef struct ct *POINTER; // Рекурсивная структура
typedef struct ct //данных.
{
int I;
POINTER P;
} CT;
POINTER R,Q,R1,Q1;
void main ()
{ // Создание первого списка.
R = new CT;
Q = new CT;
(*R).I = 15; (*Q).I = 20; (*R).P = Q; (*Q).P = NULL;
cout<<"Информационное поле второго звена списка: "
<<(*(*R).P).I<<endl;
// Создание второго списка.
R1 = new CT;
Q1 = new CT;
(*R1).I = 13; (*Q1).I = 53; (*R1).P = Q1; (*Q1).P = NULL;
cout<<"Информационное поле второго звена списка: "
<<(*(*R1).P).I<<endl;
// Работа со списками.
(*R1).P = (*R).P;
cout<<(*(*R1).P).I<<endl;
}