Студопедия
Случайная страница | ТОМ-1 | ТОМ-2 | ТОМ-3
АрхитектураБиологияГеографияДругоеИностранные языки
ИнформатикаИсторияКультураЛитератураМатематика
МедицинаМеханикаОбразованиеОхрана трудаПедагогика
ПолитикаПравоПрограммированиеПсихологияРелигия
СоциологияСпортСтроительствоФизикаФилософия
ФинансыХимияЭкологияЭкономикаЭлектроника

Теоретические сведения



Читайте также:
  1. I. ОБЩИЕ СВЕДЕНИЯ
  2. АНАМНЕСТИЧЕСКИЕ СВЕДЕНИЯ
  3. Б. Сведения о процедуре разработ­ки теста.
  4. Вопрос 18. Документы и сведения, представляемые при международной перевозке.
  5. ВОПРОС 41. Основные теоретические положения символического интеракционализма. Общая характеристика работы Г. Блумера « Коллективное поведение».
  6. Г. Сведения о размещаемых ценных бумагах.
  7. Глава 1. Теоретические аспекты изучения социальных сетей и социального пространства

Лабораторная работа № 2. Динамические массивы

Цель работы – научиться использовать операции динамического выделения и освобождения памяти на примере работы с одномерными и двумерными массивами.

Теоретические сведения

В С++ переменные могут быть объявлены статически – во время компиляции, либо динамически – во время выполнения программы. Основная разница в использовании этих методов – в их эффективности и гибкости. Статическое размещение более эффективно, так как выделение памяти происходит до выполнения программы, однако оно гораздо менее гибко, потому что мы должны заранее знать тип переменных и размерность массивов. К примеру, совсем не просто разместить содержимое некоторого текстового файла в статическом массиве строк: нам нужно заранее знать его размер. Задачи, в которых нужно хранить и обрабатывать заранее неизвестное число элементов, обычно требуют динамического выделения памяти.

При статическом выделении памяти определение переменной ival будет иметь вид:

int ival = 1024;

Приведенный выше оператор заставляет компилятор выделить в оперативной памяти область, достаточную для хранения переменной типа int, связать с этой областью имя ival и поместить в выделенную область памяти значение 1024. Эти действия производятся на этапе компиляции, до выполнения программы. С объектом ival ассоциируются две величины: собственно значение переменной, равное в данном случае 1024, и адрес той области памяти, где хранится это значение.

Для хранения данных об адресе переменной язык программирования С++ имеет встроенный тип "указатель” Чтобы объявить указатель, содержащий адрес переменной ival, мы должны объявить переменную типа указатель и передать в нее данные об адресе переменной ival с помощью оператора взятия адреса (&):

int *pint; // указатель на переменную типа int

pint = &ival; // pint получает значение адреса ival

Чтобы обратиться к той переменной, адрес которой содержит pint (в рассматриваемом примере к переменной ival), используют операцию разыменования, называемую также косвенной адресацией. Эта операция обозначается символом *. Вот как можно косвенно прибавить единицу к ival, используя ее адрес:

*pint = *pint + 1; // неявно увеличивает ival

Это выражение производит в точности те же действия, что и

ival = ival + 1; // явно увеличивает ival

На практике указатели используют чаще всего для работы с динамическими массивами.

Основные отличия между статическим и динамическим выделением памяти таковы:

· статические переменные имеют собственные имена, и действия над этими объектами производятся напрямую, с использованием их имен. Динамические переменные не имеют собственных имен, и действия над ними производятся косвенно, с помощью указателей;

· выделение и освобождение памяти, занимаемой статическими переменными, производится компилятором автоматически при выходе переменных за пределы области видимости. Программисту не нужно самому заботиться об этом. Выделение и освобождение памяти, занимаемой динамическими переменными, целиком и полностью возлагается на программиста. Для манипуляции динамически выделяемой памятью служат операторы new и delete..

Оператор new имеет две формы. Первая форма выделяет память под единичный объект определенного типа:

int *pint = new int(1024);

Здесь оператор new выделяет память под безымянный объект типа int, инициализирует его значением 1024 и возвращает адрес созданного объекта. Этот адрес используется для инициализации указателя pint. Все действия над таким безымянным объектом производятся путем разыменовывания данного указателя, т.к. явно манипулировать динамическим объектом невозможно.

Для изменения значения динамической переменной, связанной с указателем pint, необходимо использовать оператор следующего вида:

*pint = 10;

Вторая форма оператора new выделяет память под массив заданного размера, состоящий из элементов определенного типа:

int *pia = new int[4];

В этом примере память выделяется под массив из четырех элементов типа int.

Обе формы оператора new возвращают указатель на некоторую область оперативной памяти. И pint, и pia объявлены совершенно одинаково, однако pint указывает на единственный объект типа int, а pia – на нулевой элемент массива из четырех объектов типа int.

Когда динамический объект выходит за пределы области видимости, необходимо явным образом освободить выделенную для его размещения память. Это делается с помощью оператора delete, имеющего, как и new, две формы – для единичного объекта и для массива:

delete pint; // освобождение памяти, занимаемой единичным объектом

 

delete[] pia; // освобождение памяти, занимаемой массивом

Если в программе не предусмотреть использование операторов освобождения памяти, выделенной динамически, то выделенная память не будет освобождаться, и программа может аварийно завершаться из-за нехватки памяти (при условии длительной работы с программой). Небольшая утечка трудно поддается обнаружению, но существуют программные утилиты, помогающие обнаружить их.

 

Упражнение.

Объясните разницу между четырьмя объектами:

(a) int ival = 1024;

(b) int *pi = &ival;

(c) int *pi2 = new int(1024);

(d) int *pi3 = new int[1024];

При необходимости создания многомерных динамических массивов необходимо: 1) с помощью операции new выделить память под row указателей, где row – первая размерность массива, при этом все указатели располагаются в памяти последовательно друг за другом;

2) необходимо в цикле каждому указателю присвоить адрес выделенной области памяти размером, равным второй размерности массива col.

Пример.
#include <iostream.h>

void main()

{int row; // количество строк двумерного массива

int col; // количество столбцов двумерного массива

cout<< «Введите размерности массива:»;

cin>> row>>col; //определение размерностей массива (это не константы!)

int **a;// объявляем указатель на двумерный массив

a=new int*[row]; // a - указатель на массив указателей на одномерные массивы

for(int i=0;i<row;i++)

a[i]=new int[col]; // каждый элемент массива указывает на одномерный

for (i=0; i<row;i++)//Освобождение памяти от двумерного динамического массива

{for (int j=0;j<col;j++)

{a[i][j] = i*j;

cout<<a[i][j]<<' ';

}

cout<<endl;

}

for(i=0;i<row;i++) //удаление всех одномерных массивов

delete[] a[i];

delete[] a; // удаление массива указателей на одномерные массивы

}

 


Дата добавления: 2015-07-11; просмотров: 169 | Нарушение авторских прав






mybiblioteka.su - 2015-2024 год. (0.008 сек.)