Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Распределение памяти при работе программы
Схема распределения памяти под программу показана на следующем рисунке:
Область кода программы предназначена для хранения инструкций функций программы, обеспечивающих обработку данных. Данные в программе представляются переменными и константами. Для хранения глобальных данных (существуют в течение всего времени работы программы) предназначена область глобальных данных. Стек программы используется при вызове функций для передачи параметров и хранения локальных данных. Распределение памяти для хранения всех обычных переменных осуществляется компилятором, и адреса и объемы соответствующих участков памяти (в области глобальных данных) жестко закреплены за этими переменными на все время работы программы и изменено быть не может. Однако во многих задачах невозможно заранее предсказать, сколько места (количество переменных, объемы массивов и т.д.) потребуется для решения задачи – это так называемые задачи с неопределенной размерностью. Решить эту проблему можно лишь в том случае, если иметь механизм, позволяющий создавать новые объекты по мере возникновения необходимости в этих объектах или изменять объемы памяти, выделенные под эти объекты (например, объемы массивов). Между областью глобальных данных и стеком располагается так называемая динамическая область памяти, которую как раз и можно использовать в процессе работы программы для реализации механизма динамического управления памятью. Динамическое выделение и освобождение памяти в стиле C++ Для динамического управления памятью в языке C++ используются две инструкции new и delete. Формат этих инструкций:
<Переменная-указатель> = new <Тип данных переменной-указателя> delete <Переменная-указатель> Инструкция new выделяет в динамической области участок памяти, достаточный для размещения данных, тип которых определяется типом данных переменной-указателя, и возвращает адрес этого участка. Этот адрес присваивается переменной-указателю. Например:
double * p; // Переменная-указатель на тип double p = new double; // Выделение памяти
или так:
double * p = new double;
В этом примере инструкция new выделяет в динамической области участок памяти объемом sizeof (double) и присваивает адрес этого участка переменной-указателю p. Дальнейшая работа с переменной-указателем осуществляется как с обычным указателем на тип данных double. Например:
* p = 3.14; cout << * p * 2 << endl; // На экран выведено значение 6.28 cin >> * p; // Вводим с клавиатуры некоторое вещественное значение cout << * p << endl; // На экран выведено значение, введенное с клавиатуры
Размер динамической области памяти ограничен, поэтому при многократном последовательном использовании инструкции new может создаться ситуация, при которой попытка выделения очередного участка памяти с помощью операции new завершится неудачей (возникнет ошибка, связанная с переполнением динамической области памяти). Для того чтобы избежать подобных ошибок, необходимо принудительно освобождать динамическую память с помощью инструкции delete:
delete p; Инструкция delete возвращает участок памяти по адресу p в список свободной памяти, и в дальнейшем этот участок памяти может быть использован повторно для динамического размещения других данных.
Замечание. Инструкции new и delete это парные инструкции, то есть они всегда должны использоваться совместно – каждой инструкции new должна соответствовать инструкция delete. Динамическая область памяти автоматически освобождается только при завершении программы, поэтому неконтролируемое использование инструкции new может привести к переполнению динамической области памяти и, следовательно, к ошибкам в работе программы.
Тип данных переменной указателя может быть практически любым. Рассмотрим пример создания в динамической области некоторой структуры данных.
struct t_ Person // Тип данных для "персоны" { char Fam[20]; // Фамилия char Name[20]; // Имя int Year; // Год рождения }; setlocale (0, ""); // Русификация консоли
t_ Person * p = new t_ Person; // Создаем структуру в динамической памяти strcpy ((* p). Fam, "Иванов"); // Заносим фамилию strcpy ((* p). Name, "Иван"); // Заносим имя (* p). Year = 1995; // Заносим год рождения
cout << "Фамилия: " << (* p). Fam << endl; // Выводим фамилию cout << "Имя: " << (* p). Name << endl; // Выводим имя cout << "Год рождения: " << (* p). Year << endl; // Выводим год рождения
delete p; // Освобождаем память
Для обращения к отдельным полям структуры через переменную-указатель мы использовали следующие конструкции:
(*p).Fam, (*p).Name, (*p).Year
Здесь (* p) обеспечивает разыменование указателя (получение данных персоны, расположенных в памяти по адресу p), а затем с помощью оператора “точка” осуществляется обращение к данным соответствующего поля. Существует другой способ доступа к полям структур через указатель на структуру с помощью оператора “стрелка” (не требующий предварительного разыменования указателя). Это делается так:
p -> Fam, p -> Name, p -> Year
То есть следующий вариант той же программы будет также корректным:
struct t_ Person // Тип данных для "персоны" { char Fam[20]; // Фамилия char Name[20]; // Имя int Year; // Год рождения }; setlocale (0, ""); // Русификация консоли
t_ Person * p = new t_ Person; // Создаем структуру в динамической памяти strcpy (p -> Fam, "Иванов"); // Заносим фамилию strcpy (p -> Name, "Иван"); // Заносим имя p -> Year = 1995; // Заносим год рождения
cout << "Фамилия: " << p -> Fam << endl; // Выводим фамилию cout << "Имя: " << p -> Name << endl; // Выводим имя cout << "Год рождения: " << p -> Year << endl; // Выводим год рождения
delete p; // Освобождаем память
Для некоторых типов данных одновременно с динамическим выделением памяти можно осуществлять и ее инициализацию. Например:
double * p = new double (3.14); // Инициализация значением 3.14 cout << * p << endl; // На экран выведено значение 3.14
|
|||||||||||
Последнее изменение этой страницы: 2021-09-26; просмотров: 52; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.141.193.158 (0.011 с.) |