Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ГЛАВА 9. Динамические переменные и функции.doc
Скачиваний:
17
Добавлен:
29.02.2016
Размер:
137.73 Кб
Скачать

Глава 9. Динамические переменные и массивы

Динамические переменные

Одномерные динамические массивы

Двумерные динамические массивы

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

В языке С++ существует и другой способ выделения памяти для данных – во время выполнения программы. Такие данные (переменные, массивы) называются динамическими, они создаются по требованию программы и запоминаются в блоках памяти переменного размера, принадлежащих специальным образом организованной области памяти – так называемой ”куче.

Динамические переменные

В С++ наиболее распространённым способом создания динамической переменной является использование операции new и указателя:

переменная-указатель = new тип_переменной;

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

int * p = new int;

При выполнении этого оператора создаётся динамическая переменная целого типа, адрес которой присваивается указателю p.

С помощью операции new можно выделить память в куче для значений переменных любого допустимого типа.

Если свободной памяти в куче для создания новой переменной оказалось недостаточно, операция new возвращает нулевое значение (0 или NULL). Поэтому программа должна проверять успешность создания динамической переменной:

if(p == NULL){ // или if(!p)

cout<<”Error: no memory”<<endl;

exit(1);

}

При создании динамической переменной допускается сразу присвоить ей значение (проинициализировать):

int * p = new int(5);

В результате выполнения данного оператора переменной, адресуемой указателем p, будет присвоено значение 5.

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

После того как необходимость в использовании динамической переменной отпала, занимаемую её память следует освободить. Это можно сделать с помощью операции delete:

delete переменная-указатель;

Операция delete не требует указывать размер освобождаемой памяти, так как в С++ существует специальный механизм, позволяющий автоматически связывать с указателем размер области памяти, на которую он указывает.

Пример. Использование операций new, delete.

int *p = new int; // выделение памяти для int- значения

*p = 20; // занесение в эту память значения 20

cout<<*p<<endl; // вывод 20 на экран

delete p; // освобождение памяти

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

Одномерные динамические массивы

Как мы уже знаем, элементы одномерного массива располагаются в памяти компьютера подряд, начиная с адреса, соответствующего началу массива. При традиционном объявлении массива компилятору должны быть чётко указаны имя массива, размер массива и тип элементов, который явно определяет размеры памяти, выделяемой под каждый элемент массива, т.е. размер памяти, выделяемый для массива, полностью и однозначно определен.

Это не всегда удобно. Иногда нужно, чтобы память для массива выделялась в таких размерах, какие нужны для решения конкретной задачи, причем размеры памяти заранее не известны.

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

В соответствии с синтаксисом операция new при использовании с одномерным динамическим массивом имеет следующий формат:

переменная-указатель имя_массива = new тип_массива [размер];

Например, в результате выполнения оператора

int *p = new int[6];

объявляется переменная-указатель p, а затем указателю присваивается адрес выделенной области памяти для 6 элементов массива в соответствии с заданным типом массива. Если с помощью операции new невозможно выделить требуемый объём памяти, то результатом операции new является нулевое значение (0 или NULL).

Динамически созданный массив может быть удален, когда работа с ним завершена. Для освобождения памяти, выделенной для динамического одномерного массива, используют операцию delete, которая имеет следующий формат:

delete [] имя_массива;

При динамическом выделении памяти для массива следует помнить, что его нельзя одновременно и инициализировать. Размер для динамического массива может быть задан во время выполнения программы. Доступ к элементам массива возможен только через указатель – p[i], *(p + i).

Пример. Динамическое выделение и освобождение памяти для одномерного массива. Размер массива вводится с клавиатуры.

int n;

cin>>n; // n – размер массива

int* mas = new int[n]; // выделение памяти

if(!mas){cout<<"No memory"<<endl; exit(1);}

for(int i = 0; i < 6; i++ // присваивание элементам

p[i] = i + 1; ... // массива значений 1 2 3 4 5 6

delete [] mas; // освобождение памяти

Следует отметить, что оператор

int * p = new int[n];

можно разделить на два оператора

int *p; p = new int[n];

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

// Пример 9.1. Память для динамического массива выделяется

// в main(). Динамический массив создаётся в функции vvod()

// случайной выборкой. Выводится массив в функции vivod().

// В функции sum() вычисляется сумма элементов массива.

#include <iostream>

using namespace std;

void vvod(int*, int);

void vivod(int*, int);

int sum(int* a, int kol);

int main(){

int n;

cout<<"Vvedi kol-vo elementov massiva : "; cin>>n;

int* p = new int[n];

if(!p){cout<<"No memory"<<endl; exit(1);}

vvod(p, n);

cout<<"\n\tmain: Isxodni massiv =="<<endl;

vivod(p, n);

int y = sum(p, n);

cout<<"\n\tSumma = "<<y<<endl;

delete [] p;

system("pause");

}

void vvod(int* p, int n){

srand(n);

for(int i = 0;i < n; i++){

p[i] = rand() % 15 - rand() % 10;

}

}

void vivod(int* p, int n){

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

cout<<p[i]<<' '; // cout<<*(p+i)<<' ';

cout<<endl;

}

int sum(int* a, int kol){ // функция sum() вычисления суммы

int s = 0; // элементов динамического массива

for(int i = 0; i < kol; i++){

s = s + a[i];

}

return s;

}

// Пример 9.2. Память выделяется и сам массив создаётся в функции

// vvod(). Функция vvod()возвращает указатель на массив, который

// передаётся в функцию vivod(). Используется меню.

#include <iostream>

using namespace std;

void vivod(int *, int);

int* vvod(int);

int main(){

int n; int *p;

int vibor;

cout<<"vvedi kol-vo elementov massiva: "; cin>>n;

while(1){

cout<<"\n vvedite nomer punkta:\n";

cout<<"vvod---->1"<<endl

<<"vivod--->2"<<endl

<<"exit----->3"<<endl;

cin>>vibor;

switch(vibor){

case 1: system("cls"); p = vvod(n); break;

case 2: system("cls"); vivod(p, n); break;

case 3: system("cls");

cout<<"Good-Bye!"; exit(1); break;

}

}

cout<<endl;

delete [] p;

system("pause");

}

int* vvod(int n){

int *p = new int[n];

if(!p){cout<<"No memory"<<endl; exit(1);}

for(int i = 0; i < n; i++){

cout<<"vvedi a:["<<i<<"] ";

cin>>*(p + i);

}

return p;

}

void vivod(int *p, int n){

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

cout<<*(p + i )<<' '; // cout<<p[i]<<' ';

cout<<endl;

}