Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

угничтожение динамических массивов

85K
11 апреля 2013 года
VictorR
7 / / 11.04.2013
Добрый вечер!
Объясните, пожалуйста, как уничтожить динамический массив, у которого последнее измерение не динамическое. См. пример
Заранее спасибо

int m,n;
int i;

int (**X)[2];

m=10;
X=new (int(*[m])[2]);

n=20;
for(i=0;i<m;i++)
X=new int[n][2];

..............
..............

for(i=0;i<m;i++)
delete[] ????
446
11 апреля 2013 года
Meander
487 / / 04.09.2011
так:
Код:
const int     Z = 2;//чтобы не писать A[2]
  int         X = 10,//размерность 1
              Y = 20,//размерность 2
            **A[Z];//указатель на указатель на массив из двух чисел
           
  //выделяем память под первую размерность
  for(int z=0;z<Z;z++)
    A[z] = new int *[X];
  //выделяем память под вторую размерность
  for(int z=0;z<Z;z++)  
    for(int x=0;x<X;x++)  
      A[z][x] = new int [Y];
   
  //инициализируем массив, чтобы проверить правильность выделения памяти
  for(int z=0;z<Z;z++)  
    for(int x=0;x<X;x++)
      for(int y=0;y<Y;y++)
        A[z][x][y] = z*(X*Y)+y*X+x;
       
  //удаляем вторую размерность
  for(int z=0;z<Z;z++)  
    for(int x=0;x<X;x++){  
      delete [] A[z][x];
      A[z][x] = NULL;
    }
  //удаляем первую размерность
  for(int z=0;z<Z;z++){    
    delete [] A[z];
    A[z] = NULL;
  }
85K
12 апреля 2013 года
VictorR
7 / / 11.04.2013
Большое спасибо, Meander, Ваш пример понятен.
Хотелось бы, все же, понять, в чем некорректность моего варианта. Дело в том, что он нормально компилируется и правильно работает. Только вот уничтожить не получается.
446
12 апреля 2013 года
Meander
487 / / 04.09.2011
Цитата: VictorR
Хотелось бы, все же, понять, в чем некорректность моего варианта. Только вот уничтожить не получается.


Если под "моего варианта" Вы подразумеваете

 
Код:
for(i=0;i<m;i++)
  delete[] ????
то не знаю в чем некорректность (что значит "????" ?), в C++ такого оператора нет. Вы бы и сами могли проанализировать свой код.

Код:
//объявляем переменные m, n, i;
int m,n;
int i;
//объявляем два указателя на указатель
int (**X)[2];
//инициализируем переменную m
m=10;
//ячейке с адресом X[0] присваиваем указатель на указатель на двумерный массив размерности [m][2]
//а ячейке с адресом X[1] ничего не присваиваем?
X=new (int(*[m])[2]);
//инициализируем переменную n
n=20;
//двадцать раз ячейке с адресом X[0] присваиваем указатель на двумерный массив [n][2], зачем?
for(i=0;i<m;i++)
X=new int[n][2];//это не должно работать
//в итоге имеем, что память выделялась 21 раз и указатель на нее
//присваивался, только ячейке X[0], вывод: полностью память освободить не удастся
//можно освободить последнее выделение
delete [] X[0];
Вам бы получше разобраться в адресации многомерных массивов и выделении памяти.
Главное правило применения new и delete, состоит в том, что delete надо применить столько же раз сколько и new, причем в зеркальном порядке. Оператор [] вычисляет адрес ячейки памяти относительно первого элемента массива, причем первый элемент имеет наименьший адрес. Освободить память под элементы массива можно, только начиная с самых больших адресов ячеек памяти. Если прежде обнулить младший указатель, то как тогда вычислить адреса старших, чтобы и их удалить?
392
12 апреля 2013 года
cronya
421 / / 03.01.2009
вы когда выделяете память под массив у вас есть идентификатор X и при удалении должны ссылаться на него:
 
Код:
int* ptr = new int[size];//выделили память
delete[] ptr;//освободили память
а вообще у вас чего-то тут намешано, в каком учебнике так пишут интересно??

 
Код:
int (**X)[2];
m=10;
X=new (int(*[m])[2]);
85K
12 апреля 2013 года
VictorR
7 / / 11.04.2013
Что-то я совсем запутался.

В Вашем первом примере

 
Код:
const int     Z = 2;//чтобы не писать A[2]
  int         X = 10,//размерность 1
              Y = 20,//размерность 2
            **A[Z];//указатель на указатель на массив из двух чисел
разве переменная A не массив из Z указателей на указатели на int ?

А во втором:


 
Код:
//объявляем два указателя на указатель
int (**X)[2];
разве переменная X не указатель на указатель на массив из двух int ?

Объясните, пожалуйста
392
12 апреля 2013 года
cronya
421 / / 03.01.2009
у вас получается статический массив содержит динамически выделенную память, что не есть хорошо))
и что вам не понятно здесь???

Код:
//выделение паямяти
    int*** Z = new int** [2];
    for(int idx=0; idx < 2; idx++)
    {
        Z[idx] = new int* [3];
    }
    for(int idx=0; idx < 2; idx++)
    {
        for(int jdx=0; jdx < 3; jdx++)
        {
            Z[idx][jdx] = new int [4];
        }
    }
    //обращение к памяти
    for(int idx=0; idx < 2; idx++)
    {
        for(int jdx=0; jdx < 3; jdx++)
        {
            for(int kdx=0; kdx < 4; kdx++)
            {
                Z[idx][jdx][kdx] = 0;
            }
        }
    }
    //освобождение памяти
    for(int idx=0; idx < 2; idx++)
    {
        for(int jdx=0; jdx < 3; jdx++)
        {
            delete[] Z[idx][jdx];
        }
    }
    for(int idx=0; idx < 2; idx++)
    {
        delete[] Z[idx];
    }
    delete[] Z;
указатель Z указывает на область памяти размерностью 2 элемента :)
Z[2] указывает на область памяти размерностью 3 элемента :)
Z[2][3] указывает на область памяти размерностью 4 элемента :)
Z[0][0][0] указывает уже не элемент типа int, где нули - индексы элемента

85K
12 апреля 2013 года
VictorR
7 / / 11.04.2013
Спасибо, cronya. В Вашем примере мне все понятно. Еще раз спасибо.
446
12 апреля 2013 года
Meander
487 / / 04.09.2011
Формально, это одно и то же. Отличие начинает проявляться тогда, когда надо обратиться к конкретной ячейке массива. Просто в памяти компьютера нет никаких трехмерных массивов (адресация одномерная). Представлять массив как трехмерный удобно программисту, так нагляднее. Представьте двухслойную пластинку размером n*m*2. Вы можете положить ее на стол тремя способами (ось X - горизонталь (передний край стола), ось Y - от себя, ось Z - вертикаль):
1) размерностью n горизонтально перед собой (n паралельна оси x),
2) размерностью m горизонтально перед собой (m паралельна оси x),
3) размерностью 2 горизонтально перед собой (2 паралельна оси x).
Запись int **X[2] означает, что создан массив из двух элементов. Каждый элемент это указатель на указатель. Представим, что элементы X[0] и X[1] - ось x. Теперь нам надо построить плоскость xy, для этого к каждому элементу X надо прикрепить массив указателей на z длиной y. Это делается так:
 
Код:
for(int i=0;i<2;i++)
  X[i] = new int *[n];//оператор new возвращает указатель на область памяти!
Теперь у нас готова плоскость (размером x*y = 2*n) каждая ячейка которой - указатель на int. Каждому такому указателю мы должны присвоить адрес массива длиной m для того, чтобы получить измерение z:
 
Код:
for(int i=0;i<2;i++)
  for(int j=0;j<n;j++)
  X[i][j] = new int [m];//оператор new возвращает указатель на область памяти!
То есть мы ориентировали пластинку так: X=2, Y=n, Z=m, или X[x][y][z] = X[2][n][m].
Как я понял, Вам хочется обращаться к вектору из двух чисел через указатель на указатель, как будто в каждой ячейке пластинки размером n*m содержится два числа X[0] и X[1]. Тогда массив должен иметь вид X[n][m][2], а X[x][y] - указатель на массив из двух чисел: X[x][y][0] и X[x][y][1]. Чтобы получить такую конструкцию надо, просто, изменить порядок выделения памяти. Думаю Вы уже догадались как.
392
12 апреля 2013 года
cronya
421 / / 03.01.2009
если уж говорить по массивы, то в программировании нет вообще такого понятия, память выделяется блоками.
85K
12 апреля 2013 года
VictorR
7 / / 11.04.2013
Спасибо. Понял.
446
12 апреля 2013 года
Meander
487 / / 04.09.2011
Вот графическая иллюстрация трехмерной адресации

и крупный план:
Прикрепленные файлы:
125 Кб
Загрузок: 1.6K
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог