Цель лекции: изучить способы выделения памяти,
Существует два основных способа хранения информации в оперативной памяти. Первый заключается в использовании глобальных и локальных переменных. В случае
Второй способ, которым С++ может хранить информацию, заключается в использовании системы динамического распределения. При этом способе память распределяется для информации из свободной области памяти по мере необходимости. Область свободной памяти находится между кодом программы с ее постоянной областью памяти и стеком (рис 24.1). Динамическое размещение удобно, когда неизвестно, сколько элементов данных будет обрабатываться.
(рис 24.1) Распределение оперативной памяти для программ на С++По мере использования программой стековая область увеличивается вниз, то есть программа сама определяет объем стековой памяти. Например, программа с большим числом
Память, выделяемая в процессе выполнения программы, называется динамической. После выделения динамической памяти она сохраняется до ее явного освобождения, что может быть выполнено только с помощью специальной операции или библиотечной функции.
Если динамическая память не освобождена до окончания программы, то она освобождается автоматически при завершении программы. Тем не менее, явное освобождение ставшей ненужной памяти является признаком хорошего стиля программирования.
В процессе выполнения программы участок динамической памяти доступен везде, где доступен указатель, адресующий этот участок. Таким образом, возможны следующие три варианта работы с динамической памятью, выделяемой в некотором блоке (например, в теле неглавной функции).
Все переменные, объявленные в программе размещаются в одной непрерывной области памяти, которую называют сегментом данных. Такие переменные не меняют своего размера в ходе выполнения программы и называются статическими. Размера сегмента данных может быть недостаточно для размещения больших объемов информации. Выходом из этой ситуации является использование динамической памяти. Динамическая память – это память, выделяемая программе для ее работы за
Для работы с динамической памятью используют указатели. С их помощью осуществляется доступ к участкам динамической памяти, которые называются динамическими переменными. Для хранения
В С++ используется два способа работы с динамической памятью:
new и delete ;mallос ( calloc ) (унаследовано из С).В языке программирования С++ для new и delete. Эти операции используются для выделения и освобождения
Операция new позволяет выделить и сделать доступным свободный участок в основной памяти, размеры которого соответствуют типу данных, определяемому именем типа.
Синтаксис:
new ИмяТипа;
или
new ИмяТипа [Инициализатор];
В выделенный участок заносится значение, определяемое new возвращает адрес начала выделенного участка памяти. Если участок нужных размеров не может быть выделен (нет памяти), то операция new возвращает нулевое значение адреса ( NULL ).
Синтаксис применения операции:
Указатель = new ИмяТипа [Инициализатор];
Операция new float выделяет участок памяти размером 4 байта. Операция new int(15) выделяет участок памяти 4 байта и инициализирует этот участок целым значением 15. Синтаксис использования операций new и delete предполагает применение указателей. Предварительно каждый указатель должен быть объявлен:
тип *ИмяУказателя;
Например:
float *pi; //Объявление переменной pi pi=new float; //Выделение памяти для переменной pi * pi = 2.25; //Присваивание значения
В качестве типа можно использовать, например, стандартные типы int, long, float, double, char.
Оператор new чаще всего используется для размещения в памяти данных определенных пользователем типов, например, структур:
struct Node {
char *Name;
int Value;
Node *Next
};
Node *PNode; //объявляется указатель
PNode = new Node; //выделяется память
PNode->Name = "Ata"; //присваиваются значения
PNode->Value = 1;
PNode->Next = NULL;
В качестве имени типа в операции new может быть использован массив:
new ТипМассива
При выделении динамической памяти для массива его размеры должны быть полностью определены. Например:
ptr = new int [10];//10 элементов типа int или 40 байт ptr = new int [ ];//неверно, т.к. не определен размер
Такая операция позволяет выделить в динамической памяти участок для размещения массива соответствующего типа, но не позволяет его инициализировать. В результате выполнения операция new возвратит указатель, значением которого служит адрес первого элемента массива. Например:
int *n = new int;
Операция new выполняет выделение достаточного для размещения величины типа int участка динамической памяти и записывает адрес начала этого участка в переменную n. Память под саму переменную n (размера, достаточного для размещения указателя) выделяется на этапе компиляции.
int *b = new int (10);
В данном операторе, кроме описанных выше действий, производится инициализация выделенной динамической памяти значением 10.
int *q = new int [10];
В этом случае операция new выполняет выделение памяти под 10 величин типа int (массива из 10 элементов) и записывает адрес начала этого участка в переменную q, которая может трактоваться как имя массива. Через имя можно обращаться к любому элементу массива.
Есть ряд преимуществ использования new. Во-первых, операция new автоматически вычисляет размер необходимой памяти. Нет необходимости в использовании операции sizeof(). Более важно то, что она предотвращает случайное выделение неправильного количества памяти. Во-вторых, операция new автоматически возвращает указатель требуемого типа.
Для освобождения выделенного операцией new участка памяти используется операции:
delete указатель;
Указатель адресует освобождаемый участок памяти, ранее выделенный с помощью операции new. Например:
delete x;
Для
delete [ ] указатель;
Операцию delete следует использовать только для указателей на память, выделенную с помощью операции new. Использование delete с другими типами адресов может породить серьезные проблемы.
Пример 1. Демонстрация выполнения операций с динамической памятью.
#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[]){
int *pa, *pb;
pa = new int;
*pa = 21;
pb = pa;
cout << *pa << " " << *pb << "\n";
pb = new int;
*pb = 28;
cout << *pa << " " << *pb << "\n";
delete pa;
pa = pb;
cout << *pa << " " << *pb << "\n";
delete pa;
system("pause");
return 0;
}
Результат выполнения программы:
21 21 21 28 28 28
Средства для динамического выделения и malloc.h и stdlib.h malloc.h ).
| Функция | Прототип и краткое описание |
|---|---|
malloc |
void * malloc ( возвращает указатель на начало области (блока) динамической памяти длинной в s байт. При неудачном завершении возвращает значение NULL. |
calloc |
void * calloc ( возвращает указатель на начало области (блока) обнуленной динамической памяти, выделенной для размещения n элементов по m байт каждый. При неудачном завершении возвращает значение NULL. |
|
void * изменяет размер блока ранее выделенной динамической памяти до размера ns байт, bl – адрес начала изменяемого блока. Если bl равен NULL (память не выделялась), то функция выполняется как malloc. |
free |
void * free (void * bl); освобождает ранее выделенный участок (блок) динамической памяти, адрес первого байта которого равен значению bl. |
Функции malloc(), calloc() и динамически выделяют память в соответствии со значениями параметров и возвращают адрес начала выделенного участка памяти. Для универсальности тип void *. Этот указатель можно преобразовать к указателю любого типа с помощью операции явного тип * ).
Функция free() освобождает память, выделенную перед этим с помощью одной из трех функций malloc(), calloc() или . Сведения об участке памяти передаются в функцию free() с помощью указателя – параметра типа void *. Преобразование указателя любого типа к типу void * выполняется автоматически, поэтому вместо void *bl можно подставить в качестве
Пример 2. Ввести и напечатать в обратном порядке набор вещественных чисел, количество которых заранее не фиксировано, а вводится до начала ввода самих числовых значений.
#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[]){
float* t; //Указатель для выделяемого блока памяти
int i,n;
printf("n=");//n - число элементов
scanf("%d", n);
t=(float *)malloc(n*sizeof(float));
for (i=0; i<n; i++){ //цикл ввода чисел
printf("x[%d]=",i);
scanf("%f", t[i]);
}
//цикл печати результатов
for (i=n-1; i>=0; i--){
printf("\nx[%d]=%f",i,t[i]);
}
free(t); //освобождает память
system("pause");
return 0;
}
В программе int n – количество вводимых чисел типа float, float* t – указатель на начало области, выделяемой для размещения n вводимых чисел. Указатель t принимает значение адреса области, выделяемой для n значений типа float. Доступ к участкам памяти выделенной области выполняется с помощью операции индексирования: t[i] и t[i-1]. Оператор free(t); содержит вызов функции, освобождающей выделяемую ранее динамическую память и связанной с указателем t.
Динамическая память – это память, выделяемая программе для ее работы за
Динамические переменные – это переменные, определенные в области динамической памяти.
Операция выделения динамической памяти – это выделение достаточного для размещения величины участка динамической памяти.
Операция освобождения динамической памяти – это освобождение участка динамической памяти, выделенного ранее.
Сегмент данных – это непрерывная область памяти, в которой размещаются объявленные в программе переменные.
Функция выделения динамической памяти – это функция выделения памяти в соответствии со значениями параметров, возвращающая адрес начала выделенного участка памяти.
Функция освобождения динамической памяти – это функция освобождения динамической памяти, выделенной ранее.
Цель работы: изучить способы выделения памяти,
При выполнении лабораторной работы для каждого задания требуется написать программу на языке С++, которая получает на входе данные в соответствии с указанном в задании типом и осуществляет их обработку, используя для хранения оговоренных в условии последовательностей ресурсы динамической памяти. Ввод данных осуществляется с клавиатуры с учетом содержащихся в постановке задачи признака конца входной последовательности данных и требований к ним. Ограничениями на входные данные является максимальный размер строковых данных, допустимый диапазон числовых типов в языке С++ и максимально допустимый размер динамической памяти.
Теоретические сведения.
Ознакомьтесь с материалом лекции 24.
Задания к лабораторной работе.
Выполните приведенные ниже задания.
new и delete ; 2) с помощью библиотечных функций malloc (calloc) и free.an an-1 ... a3 a2 a1 an-1 an-2 ... a2 ..................
Указания к выполнению работы.
Каждое задание необходимо решить в соответствии с изученными методами работы с динамической памятью и алгоритмами обработки данных в языке С++. В задачах 2, 3 и 4 количество входных данных заранее не определено, однако, при реализации следует считать, что их размер не превышает максимально допустимого объема динамической памяти. Вывод результатов обработки данных следует осуществить на экран. Программу для решения каждого задания необходимо разработать методом процедурной абстракции, оформив комментарии к коду.
Следует реализовать каждое задание в соответствии с приведенными этапами:
Требования к отчету.
Отчет по лабораторной работе должен соответствовать следующей структуре.
Контрольные вопросы
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.