Динамическое распределение памяти. 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Динамическое распределение памяти.



 

malloc

calloc

realloc

free

int Mbyte=…;

int *p=static_cast<int*>(malloc(Mbyte));

if (p)…

size_t n=_msize(p)

calloc - обнуляет содержимое памяти

realloc - изменяет размер ранее захваченного блока памяти

p=ststic_cast<int*> realloc(p,2000);

free - освобождается выделенная память

free(p)

 

Управление памятью. Оператор new и delete.

 

Преимущество new и delete:

1.  необязательно явно указывать количество требуемых байт;

2.  результатом выделившейся памяти с помощью malloc является указатель с типом <void *>, в случае использования new: компилятор неявно приводит тип указателя к указанному типу;

3. оператор new совмещает выделившуюся память с вызовом инициализирующей функции;

int *p=new int; //sizeof(int)

                     malloc(4)

int *p=operator new (sizeof(int));

При динамическом выделении памяти из-за большого количества информации, «накладные» расходы достаточно велики.

delete(p);

 

Оператор new и массивы.

 

 Создавать массивы следует только тогда, когда:

1. все или некоторые размерности массива определяются только во время выполнения программы;

2. размерности массива могут измениться в процессе программы.

Не стоит забывать об удалении (освобождении) динамически занятой памяти.

int n= выражение;

//int ar[n]; // ERROR!!!

int *pn=new int[n]; //выделившийся в памяти блок размером n*sizeof(int)+служебная информация

 

 

pn[i]=…;

int *tmp=new int[n*z];

for (int i=0; i<n; i++){tmp[i]=pn[i];}

memcpy(tmp,pn,n*sizeof(int));

delete[]pn;

pn=tmp;

pn[i]=…;

delete[]pn;

delete[]tmp;

pn= Ø;

tmp= Ø;

 

Многомерные массивы.

 

pf=new float[n][2]; //создали массив векторов

delete []pf;

int M= выражение;

int N= выражение;

int *p=new int[M*N];

p[i*M+j]=…;

 Операция new в памяти более сложна, чем выделение, т.к. программист явно или неявно передаёт информацию о количестве элементов, а оператор delete получает только титрированный указатель.

 Проблема состоит в определении: является ли данный указатель указателем на одиночный объект или на массив объектов. Для этих целей в C++ существует две формы delete:

1. delete для одиночных объектов;

2. delete для массива.

 

Ссылки.

 

Косвенное обращение к объекту.

 Указатель (pointer) – переменная,                  Ссылка (reference)

переменная, которая явно содержит адрес объекта. которая тоже содержит адрес объекта, но синтаксически ею пользуется также, как и самим объектом.

1. Объявление:

                int *p=&x;                                                int &r=x; // ссылка с именем

 

2. Инициализация:

              int *p; //OK                                                  //int &r; // ERROR!!!

3. Получение значений:

             int tmp=*p;                                                      int tmp=r;

         (*p)++;                                                  r++;

Примечание. Ссылку можно интерпретировать как константный указатель, при каждом использовании которого, автоматически происходит разыменование.

4. Модификация адреса.  Если указатель не объявлен как константный, то значение такого адреса можно изменять. Ссылка тоже содержит адрес, но этот адрес формируется один раз при инициализации, и изменить его невозможно.

  p++; //OK                                          r++;

  int y;                                                int y=5;

  p=&y; //OK                                          r=y; //r=y=x=5;

Комментарий: переменной x (адрес которой содержится в ссылке r) будет присвоено значение y.

 

5. Нулевое значение. Указатель может быть равен нулю (никуда не указывает). Ссылка всегда содержит адрес того объекта, которым она была проинициализирована.

     if (p)                                                         if (r)

 

6. Применение оператора &. Чтобы получить указатель на объект, псевдонимом которого является ссылка r, можно применить к ссылке операцию получения адреса объекта (&).

       int **pp=&p;                                         int *pr=&r; (указывает на объект, псевдоним

которого является

       int y=**pp;                                                   

                                                                     ссылка, то есть pr                                                                       содержит адрес r

                                                                           переменной x

7. Ссылка на указатель.

     int n;                                            ссылки на ссылку не

                                                                 существует

       int *p=&n;                                                     int n;

       int *&refp=p;                                                          int &r=n;

       *ref p=2; //n=2;                                                    int &rr=r; // ERROR!!!

       *p=4;

8. void

        void *p; //OK                                               void &r=x; 

//ERROR!!!

 не знаем какого типа или какая память выделится т.к. ссылка – это всегда псевдоним совершенно определённого объекта

9. size of

    double *p;                                                 double d;

    size_t n=sizeof(p); //4 байта                            double &rd=d;

                                                                             size_t n=sizeof(rd); //8 байт

10.   Инициализация литералом.

     константная ссылка

int *p=0x10000000; //ERROR!// СИ           int &r=1; //ERROR!!!

int *p=(int*)0x10000000; //OK!// СИ ++   const int &r=1; //OK!

int *p=reinterpret_cast<int*>(0x10000000);

 

Функции.

 

 Функция – часть программы, которая принимает параметры, выполняет инструкции, называемые телом функции, а затем возвращает управление вызывающей программе.

Функции позволяют:

1.   не писать многократно один и тот же код, который выполняет одни и те же действия с разными наборами данных;

2.  позволяет использовать посредством функций чужой код;

3.  улучшить структуру программы;

4.  справиться со сложностью восприятия больших программ.

 Объявление функции: предварительное описание, которое извещает компилятор о типе возвращаемого значения, количестве и типах передаваемых аргументов.

 Используя прототип, компилятор может выполнить контроль числа аргументов и проверить соответствие их типов при вызове функции.

 При необходимости компилятор может произвести неявное преобразование типа.

[спецификатор][тип][соглашение по вызову] имя_функций ([список_аргументов] //[void])

или

[] - необязательно, () – обязательно.

Спецификатор: соглашение по функции.

 [Тип]: задаёт тип возвращённое функцией значение.

 Если поле отсутствует, то функция должна возвращать int.

 Если void      не возвращает значение

 char MyFunc()

 char MyFunc()

 void MyFunc() //тип возвращённого значения – int

Имя функции – особый тип указателя, называется указателем на функцию. Его значение является адрес-точка входа в функцию.

Список аргументов. Определяет количество и тип аргументов (параметров), передаваемых в функцию.

Список_аргументов==тип_аргумента1[имя_аргумента1], тип_аргумента2[имя_аргумента2]…

 Если в функцию не передавать аргументы, то поле пустое или содержит void.

 



Поделиться:


Последнее изменение этой страницы: 2021-12-15; просмотров: 34; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.144.42.196 (0.015 с.)