Доступ к двойному указателю вызывает ошибку сегментации - PullRequest
1 голос
/ 16 сентября 2011

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

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

enter code her    enter code here
int i, j, k;  


//== BEGIN MAIN ==//
int main ()
{
  //Constants and variables          
  double **A;
  double epsilon = pow((double)10, double(-8)); //The convergence limit for jacobis   method
  int N          = 10;                          //Dimension of matrix
  char test[] =  "test";
  cout <<"The inner matrix function:"<<endl;
  makematrix(N, A);
  cout<<endl<<"The outer matrix function:"<<endl;
  //This part segfaults
  for(i=0; i<N; i++)
  {
  cout<<endl;
  for(j=0; j<N; j++)
{
  cout<<A[i][j]<<" ";
}
 }
return 0;
 }
 //== END MAIN ==//



//==Begin function definitions==//
void makematrix(int N, double **A)
{
   //Function for initializing our tridiagonal matrices for jacobis method
    A = new double*[N];
for(i=0; i<N; i++)
{
  A[i] = new double[N];
}
 for(i=0; i<N; i++)
{
  for(j=0; j<N; j++)
{
  A[i][j] = 0;
   }
     }
    //Prints the matrix declared here
    for(i=0; i<N; i++)
     {
       cout<<endl;
       for(j=0; j<N; j++)
    {
      cout<<A[i][j]<<" ";
    }
    }
 cout <<endl;
 return;
}

Ответы [ 5 ]

3 голосов
/ 16 сентября 2011

Вернуть:

double** makematrix(int N) {
    double **A = new double*[N];
    ...
    return A;
}

В основном ...

double **A = makematrix(N);
2 голосов
/ 16 сентября 2011
//This part segfaults
  for(i=0; i<N; i++)

Потому что вы передаете double **A по значению (которое изменяется внутри makematrix), а не по ссылке.Измените подпись вашей функции на следующую, и она должна работать:

void makematrix(int N, double **&A)
...                            ^^^ pass by reference
1 голос
/ 16 сентября 2011

Поскольку, когда вы передаете A в функцию, функция работает с копией из A. Он устанавливает эту копию в массив new, но это не влияет на оригинал A.

Одно из решений:

double **A;

makematrix(N, &A);  // Pass address of A

...

void makematrix(int N, double ***A)
{
    (*A) = new double*[N];
    // etc.
}

т.е. передать адрес A, чтобы функция могла изменить оригинал.

Примечание: Каждый раз, когда вам в конечном итоге понадобятся тройные указатели, у вас, вероятно, будут проблемы с дизайном. Особенно в C ++.

0 голосов
/ 16 сентября 2011

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

Однако, если вы хотите кодировать в реальном C ++, а не в замаскированном C,Чтобы скрыть сложность двойного массива за вашей матрицей, нужно создать класс.C ++ FAQ Lite содержит подробное описание вашей проблемы и различные подходы к ее решению.См http://www.parashift.com/c++-faq-lite/operator-overloading.html#faq-13.10 и http://www.parashift.com/c++-faq-lite/operator-overloading.html#faq-13.11

0 голосов
/ 16 сентября 2011

Я полагаю, вы должны передать указатель в качестве параметра по ссылке. Таким образом, функция должна выглядеть следующим образом (я добавил &):

void makematrix(int N, double **&A)

Таким образом, ваша переменная будет изменена, поэтому теперь A является выходным параметром.

...