Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Массивы указателей. Двумерные динамические массивы




Гибкость семейства языков программирования, относимых к С++ позволяет организовать хранение многомерных массивов данных многими способами. Рассмотрим способ, основанный на выделении динамической памяти под матрицу в виде указателя **Name на массив указателей, содержащий адреса строк (или столбцы) матрицы.

Этот способ выделения памяти под двумерный массив состоит из двух этапов – сперва формируется массив указателей на строки (или столбцы) матрицы, а затем в цикле создаются одномерные массивы для хранения переменных заданного типа (Рис. 19), память под которые так же выделяется динамически:

//выделение динамической памяти под массив указателей ИмяМассива= new Тип * [ВыражениеТипаКонстанты]; Цикл (условие) { //выделение динамической памяти для массивов значений ИмяМассива[ЗначениеИндекса] = new Тип [ВыражениеТипаКонстанты]; }

Рис. 19. Расположение двумерного массива в динамической памяти

Например:

// Динамический захват и освобождение памяти double *a; // Одна переменная double *d; // Массив переменных double **dd; // Двумерный массив – массив указателей const int M= 4; // размерность матрицы N*M const int N= 3; // Захват памяти a = new double; // Одна переменная d = new double[M]; // Одномерный массив переменных [M] // Двумерный массив [N*M] dd = new double*[N]; // массив указателей for (int i=0; i<N; i++) dd[i] = new double[M]; // массивы значений матрицы

При таком способе выделения памяти переменная dd фактически представляет собой «указатель на указатель на ячейку типа double». Команда dd= new double[N] создает массив указателей, каждая ячейка которого представляет собой адрес одного из N одномерных массивов dd[i], предназначенных для хранения собственно значений матрицы. На начальном этапе массив указателей не заполнен, поэтому дальше в цикле по счетчику i от 0 до N выделяется память под одномерные массивы значений dd[i] и адреса этих массивов (их нулевой ячейки) сохраняются в соответствующих ячейках массива указателей dd.

Так как функции malloc() и calloc() возвращают нетипизированный указатель void *, то необходимо выполнять его явное преобразование в указатель объявленного типа:

int n, m; // n и m – количество строк и столбцов матрицы float **matr; // указатель для массива указателей matr= (float **) malloc(n*sizeof(float *)); // выделение динамической памяти под массив указателей for (int i=0; i<n; i++) // выделение динамической памяти для массива значений matr[i]= (float *) malloc(m*sizeof(float));

Адресация элементов динамического массива такого вида осуществляется с помощью индексированного имени:

ИмяМассива[ВыражениеТипаКонстанты][ВыражениеТипаКонстанты]; ИмяМассива[ЗначениеИндекса][ЗначениеИндекса];

Рассмотрим присвоение значений переменной-указателю a, одномерному массиву – вектору b и двумерному массиву – матрице dd.

*a = 1.0; // Содержимому указателя а присвоить 1 cout << "a = " << *a << endl; // значение содержимого cout << "адрес переменной a = " << a << endl; // адрес // Вектор переменных (одномерный массив) cout << "адрес вектора d = " << d << " содержимое вектора:\n"; for (int i=0; i<M; i++) { d[i] = double(i); // значения элементов массива cout << "d[" << i << "] = " << d[i] << endl; } // Матрица (двумерный массив) cout << "адрес двумерного массива " << dd << " содержимое матрицы:\n"; for (int i=0; i<N; i++, cout << endl) // Двумерный массив for (int j=0; j<M; j++) { dd[i][j] = (double)(i + j); cout<< "dd[" << i <<"]["<< j <<"]="<< dd[i][j] << endl; }

Удаление из динамической памяти двумерного массива осуществляется в порядке, обратном его созданию, то есть сначала освобождается память, выделенная под одномерные массивы с данными dd[i], а затем память, выделенная под одномерный массив указателей dd.

Участок памяти, выделенный ранее операцией new, освобождается при помощи операции освобождения памяти delete.

Цикл (условие) { delete ИмяМассива [ЗначениеИндекса]; } delete [] ИмяМассива;

Например:

//освободить память, выделенную для N массивов значений for (int i=0; i<N; i++) delete dd[i]; //освободить память, выделенную под массив указателей delete []dd;

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

(!) Необходимо четко представлять себе, что удаление памяти, выделенной под массив указателей до того, как будет освобождена динамическая память массивов значений приведет к ошибке. Так как адреса массивов значений dd[i] будут утрачены, не будет возможности обратиться к массивам dd[i] для освобождения занятой ими памяти. Эта «потерянная» часть динамической памяти будет не доступна для программы пользователя и не сможет быть перераспределена диспетчером памяти операционной системы другим программам, так как она выделялась под пользовательское приложение. Это основная ошибка при работе с динамической памятью.

Участок памяти, выделенный ранее операцией при помощи библиотечных функций malloc() и calloc() освобождается при помощи библиотечной функции free():

//освободить память, выделенную для массива значений for (int i=0; i<n; i++) free (matr[i]); //освободить память, выделенную под массив указателей free (matr);
Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...