Удаление двойного указателя (матрицы) - PullRequest
0 голосов
/ 24 сентября 2011

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

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

void hamiltonian(int, double **&);

int i,j;

int main()
{
int N = 1000; double **A;

hamiltonian(N, A);

//Physics here
.
.
.
.
.
//Delete
for(i=0; i<N; i++){delete []A[i];}
delete []A;

return 0;
}

void hamiltonian(int N, double **&A)
{
A = new double *[N];
for(i=0; i<N; i++)
{
A[i] = new double[N];
for(j=0; j<N; j++)
{
if(i==j)A[i][j] = 2;
if(i==j+1 || i==j-1){A[i][j] = 1;}
}
}
}

По словам моего профессора, мне приходится освобождать в той же функции, что и я, но я даже не думал об освобождении после того, как почти закончил свой проект, поэтому мне приходится переписывать много кода,проблема в том, что я не могу освободить A внутри функции гамильтониана, как мне нужно в других функциях (внутри //Physics).

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

Ответы [ 3 ]

2 голосов
/ 24 сентября 2011

По словам моего профессора, я должен освобождать в той же функции, что и я

Это чистая глупость. Иногда (почти всегда) вам нужно использовать выделенную структуру вне функции. Определенно ложно для объектов, поскольку конструкторы и деструкторы - это разные функции.

В любом случае, вы можете уйти без использования классов, если вы создадите матрицу struct и связанные функции newMatrix и deleteMatrix:)

#include <cstddef>
#include <iostream>

using namespace std;

struct Matrix
{
    int n;
    int m;
    double** v;
};

Matrix newMatrix (int n, int m)
{
    Matrix A;
    A.n = n;
    A.m = m;
    A.v = new double*[n];
    for( int i = 0; i < n; i++ ){
        A.v[i] = new double[m];
    }
    return A;
}

Matrix newHamiltonianMatrix (int n, int m)
{
    Matrix A = newMatrix(n, m);
    for( int i = 0; i < A.n; i++ ){
        for( int j = 0; j < A.m; j++ ){
            A.v[i][j] = 0.0;
            if( i == j ){
                A.v[i][j] = 2.0;
            }
            if( i == j + 1 or i == j - 1 ){
                A.v[i][j] = 1.0;
            }
        }
    }
    return A;
}

void deleteMatrix (Matrix A)
{
    for( int i = 0; i < A.n; i++ ){
        delete [] A.v[i];
    }
    delete [] A.v;
    A.v = NULL;
}

int main ()
{
    Matrix A = newHamiltonianMatrix(10, 20);
    for( int i = 0; i < A.n; i++ ){
        for( int j = 0; j < A.m; j++ ){
            cout << A.v[i][j] << " ";
        }
        cout << endl;
    }
    deleteMatrix(A);
}
2 голосов
/ 24 сентября 2011
delete A;

Должен быть

delete[] A;

Если вы new[] это, вы ДОЛЖНЫ delete[] это.Также используйте vector - они позаботятся о себе.

vector<vector<double>> matrix;
0 голосов
/ 24 сентября 2011

Есть несколько проблем с вашим кодом.

(1) Вы не выделяете памяти членам указателя A.то есть A[i] не выделяются с new[].Таким образом, доступ к ним - это неопределенное поведение .

(2) Вы должны сделать delete[] для указателя, если он был выделен с помощью new[].В вашей другой функции delete A; не так.Используйте delete[] A;

(3) Использование new/new[] - не единственный способ выделения.На самом деле вы должны использовать такое динамическое распределение, когда не осталось выбора.Из вашего кода кажется, что вы жестко кодируете N=1000.Так что лучше использовать 2D массив.

const int N = 1000;  // globally visible
int main ()
{
  double A[N][N];
  ...
}
void hamiltonian (double (&A)[N][N])
{
  ...
}
...