угничтожение динамических массивов
Объясните, пожалуйста, как уничтожить динамический массив, у которого последнее измерение не динамическое. См. пример
Заранее спасибо
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[] ????
Код:
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;
}
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;
}
Хотелось бы, все же, понять, в чем некорректность моего варианта. Дело в том, что он нормально компилируется и правильно работает. Только вот уничтожить не получается.
Цитата: VictorR
Хотелось бы, все же, понять, в чем некорректность моего варианта. Только вот уничтожить не получается.
Если под "моего варианта" Вы подразумеваете
Код:
for(i=0;i<m;i++)
delete[] ????
delete[] ????
Код:
//объявляем переменные 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];
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, причем в зеркальном порядке. Оператор [] вычисляет адрес ячейки памяти относительно первого элемента массива, причем первый элемент имеет наименьший адрес. Освободить память под элементы массива можно, только начиная с самых больших адресов ячеек памяти. Если прежде обнулить младший указатель, то как тогда вычислить адреса старших, чтобы и их удалить?
Код:
int* ptr = new int[size];//выделили память
delete[] ptr;//освободили память
delete[] ptr;//освободили память
Код:
int (**X)[2];
m=10;
X=new (int(*[m])[2]);
m=10;
X=new (int(*[m])[2]);
В Вашем первом примере
Код:
const int Z = 2;//чтобы не писать A[2]
int X = 10,//размерность 1
Y = 20,//размерность 2
**A[Z];//указатель на указатель на массив из двух чисел
int X = 10,//размерность 1
Y = 20,//размерность 2
**A[Z];//указатель на указатель на массив из двух чисел
А во втором:
Код:
//объявляем два указателя на указатель
int (**X)[2];
int (**X)[2];
Объясните, пожалуйста
и что вам не понятно здесь???
Код:
//выделение паямяти
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;
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] указывает на область памяти размерностью 3 элемента :)
Z[2][3] указывает на область памяти размерностью 4 элемента :)
Z[0][0][0] указывает уже не элемент типа int, где нули - индексы элемента
Спасибо, cronya. В Вашем примере мне все понятно. Еще раз спасибо.
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[i] = new int *[n];//оператор new возвращает указатель на область памяти!
Код:
for(int i=0;i<2;i++)
for(int j=0;j<n;j++)
X[i][j] = new int [m];//оператор new возвращает указатель на область памяти!
for(int j=0;j<n;j++)
X[i][j] = new int [m];//оператор new возвращает указатель на область памяти!
Как я понял, Вам хочется обращаться к вектору из двух чисел через указатель на указатель, как будто в каждой ячейке пластинки размером n*m содержится два числа X[0] и X[1]. Тогда массив должен иметь вид X[n][m][2], а X[x][y] - указатель на массив из двух чисел: X[x][y][0] и X[x][y][1]. Чтобы получить такую конструкцию надо, просто, изменить порядок выделения памяти. Думаю Вы уже догадались как.
если уж говорить по массивы, то в программировании нет вообще такого понятия, память выделяется блоками.
Спасибо. Понял.
Вот графическая иллюстрация трехмерной адресации