Динамические одномерные массивы
Поможем в ✍️ написании учебной работы
Поможем с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой

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

Для работы с динамическими массивами требуется сначала объявить указатель требуемого типа данных, например,

double *uk_mas;

Затем где-нибудь в программе выделить память в куче для массива

uk_mas = new double[50];

После этого с массивом можно работать обычным образом, например,

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

uk_mas[i] = rand()%100;

После работы с массивом следует освободить его память операцией

delete[] uk_mas;

Теперь можно снова использовать освобожденный объем памяти посредством повторного резервирования памяти. Если в операторе delete не указать квадратные скобки, то результат его работы окажется непредсказуемым.

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

Если размер массива точно не определен или массив очень большой, то лучше использовать динамические массивы, объявленные с применением указателей.

Пример

Дан массив из 100 целочисленных элементов. Создать другой массив, содержащий только четные элементы исходного массива.

 

#include <iostream>

#include <iomanip>

#include <cstdlib>

const int M = 100;

 

int main ()

{  int mas[M];  

int *ukm;          // указатель на целое

int k = 0;           // счетчик четных элементов

j = 0;                 // для нового массива

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

{ mas[i] = rand() % 100 – 50;

  cout << setw(4) << mas[i];

  if (mas[i] % 2 == 0)

      k++;

}

cout << endl;

ukm = new int[k];                 

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

{ if (mas[i] % 2 == 0)

       { ukm[j] = mas[i];

           cout << setw(4) << ukm[j]; // вывод значений нового массива

           j = j + 1;

        }

}

cout << endl;

return 0;

}

 Указатели и матрицы

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

int matr[4][2];         // массив [4×2]

int *uk_matr;           // указатель на целый тип

В этом случае uk_matr = matr указывает на первый элемент первой строки: uk_matr == &matr[0][0], uk_matr + 1 – на matr[0][1] и так далее согласно расположению элементов массива в памяти, которое всегда однозначно (сначала запоминаются элементы первой строки, за ней – элементы второй строки и так далее).

 

ukmatr        ukmatr + 1     ukmatr + 2     

     
 


matr[0][0] matr[0][1] matr[1][0] matr[1][1]

              matr

 

Тогда

uk_matr == &matr[0][0]

uk_matr + 1 == &matr[0][1]

uk_matr + 2 == &matr[1][0]

uk_matr +5 == &matr[2][1]

или

matr[0] == &matr[0][0]

matr[1] == &matr[1][0] и так далее.

 

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

1) int *uk_ma = new int[row*col]; … delete[]uk_ma;

2) uk_ma = malloc(row*col*sizeof(int));  free(uk_ma);

Но тогда в куче будет выделен сплошной кусок памяти, что неэффективно для матриц больших размеров.

Чаще выделение памяти под матрицу выполняют иначе.

Пусть требуется создать двумерный динамический массив целых чисел размерностью n*m.

int m, n, i;

int **mas;                       // указатель на указатель типа int

cin << n;                         // число строк матрицы

cin << m;                         // число столбцов матрицы

mas = new int* [n];           // выделяется память под n указателей на строку

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

mas[i] = new int[m];      // выделяется память для каждой строки

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

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

delete [] mas;

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

Пример

Найти максимальный элемент каждого столбца в двумерном массиве и переписать эти значения в одномерный массив (всё в динамических массивах)

 

#include <iostream>
#include <ctime>   
#include <iomanip>
#include <cstdlib>

 

using namespace std;

int main()
{
const int rows=5;
const int cols=5;
srand(time(0));                  // перемешиваем базу случайных чисел
// создаем указатель на матрицу, указатель на одномерный массив и выделяем память
float **ptr2arr = new float *[cols];
float *ptrmax = new float[cols];
for (int count=0;count<rows; count++)
ptr2arr[count] = new float[cols];
// заполняем матрицу вещественными случайными числами
for (int count_row =0; count_row <rows; count_row++)
{
for (int count_col=0;count_col<cols;count_col++)
    ptr2arr[count_row][count_col] = ((rand()%10+1) / float(rand()%10+1));
}
// выводим матрицу
for (int count_row = 0; count_row < rows; count_row++)
{
    for (int count_col =0; count_col < cols; count_col++)
       cout « setw(4) « setprecision(2) « ptr2arr[count_row][count_col] « " ";
       cout « endl;
  }
/* находим максимальный элемент каждого столбца в матрице и переписываем эти значения в  одномерный массив */
cout « "-------------------------------------------\n";

for (int count_col =0; count_col < cols; count_col++)
{
     ptrmax[count_col]=0;
     for (int count_row=0;count_row < rows; count_row++)
     {
        if(ptr2arr[count_row][count_col] >= ptrmax[count_col])
            ptrmax[count_col] = ptr2arr[count_row][count_col];
     }

     cout « setw(4) « setprecision(2) « ptrmax[count_col]«" ";
}
// удаляем занимаемую массивами память (отдаем в переиспользование)
for (int count=0; count < rows; count++)
    delete ptr2arr [count];
delete [] ptrmax;
delete [] ptr2arr;
return 0;
}












































Дата: 2019-05-28, просмотров: 208.