2016-11-28 3 views
0

私はC++が新しく、ポインタへのポインタを使用して3次元配列を作成しようとしています。私はそうすることでもっと効率的な方法があると確信していますが、現時点でポインタを理解しようとしています。C++でポインタを使用している配列:返された配列にアクセスする際のセグメンテーションフォールト

サンプルコードとして、私はもともと、メモリを割り当て、初期化、および解放するうまく動作した次の部分を持っていました。

void builder(int aSize1, int aSize2, int aSize3) 
{ 
    int i1, i2, i3; 
    int ***frequencies; 

    cout << "allocation started ..." << endl; 
    frequencies = new int** [aSize1+1]; 
    for (i1=0; i1<=aSize1; i1++){ 
     frequencies[i1] = new int*[aSize2+1]; 
     for (i2 = 0; i2 <= aSize2; i2++) 
     { 
      frequencies[i1][i2] = new int [aSize3 + 1]; 
     } 
    } 
    cout << "allocation done" << endl; 
    cout << " " << endl; 

    cout << "before initialization" << endl; 
    for (i1=0; i1<=aSize1; i1++){ 
     for(i2=0; i2<=aSize2; i2++){ 
      for(i3 = 0; i3 <= aSize3; i3++) 
      { 
       frequencies[i1][i2][i3]= (i1 * i2) % 10; 
      } 
     } 
    } 
    cout << "after initialization" << endl; 
    cout << " " << endl; 

    /* the "destroyer" part */ 

    cout << "deleting ..." << endl; 

    for (i1=0; i1<=aSize1; i1++){ 
     for(i2=0; i2<=aSize2; i2++){ 
      delete [] frequencies[i1][i2]; 
     } 
    } 

    for (i1=0; i1<aSize1; i1++){ 
     delete [] frequencies[i1]; 
    } 
    delete [] frequencies; 
    cout << "deleting done" << endl; 

} 

は私が私のプログラムのmain()機能で初期化配列を使用することができるように、いくつかの部分に上記のコードを分割することによって、アンティアップしたかった(私はそこにもそれらにアクセスできるかどうかだけを参照します) 。

void builder(int aSize1, int aSize2, int aSize3, int*** frequencies) 
{ 
    int i1, i2, i3; 
    //int ***frequencies; 

    cout << "allocation started ..." << endl; 
    frequencies = new int** [aSize1+1]; 
    for (i1=0; i1<=aSize1; i1++){ 
     frequencies[i1] = new int*[aSize2+1]; 
     for (i2 = 0; i2 <= aSize2; i2++) 
     { 
      frequencies[i1][i2] = new int [aSize3 + 1]; 
     } 
    } 
    cout << "allocation done" << endl; 
    cout << " " << endl; 

    cout << "before initialization" << endl; 
    for (i1=0; i1<=aSize1; i1++){ 
     for(i2=0; i2<=aSize2; i2++){ 
      for(i3 = 0; i3 <= aSize3; i3++) 
      { 
       frequencies[i1][i2][i3]= (i1 * i2) % 10; 
      } 
     } 
     cout << **(frequencies[i1]+2) << endl; 
    } 
    cout << "after initialization" << endl; 
    cout << " " << endl; 

} 

void destroyer(int aSize1, int aSize2, int aSize3, int*** frequencies) 
{ 
    int i1, i2; 

    cout << "deleting ..." << endl; 

    for (i1=0; i1<=aSize1; i1++){ 
     for(i2=0; i2<=aSize2; i2++){ 
      delete [] frequencies[i1][i2]; 
     } 
    } 

    for (i1=0; i1<aSize1; i1++){ 
     delete [] frequencies[i1]; 
    } 
    delete [] frequencies; 
    cout << "deleting done" << endl; 
} 

と私は無益な努力で3Dアレイにアクセスしようとする私のmain()を:だから、私は、次の

ヘッダファイルをやってしまいました。

int main() 
{ 
    int aSize1 = 10; 
    int aSize2 = 10; 
    int aSize3 = 10; 
    int*** freq; 

    builder(aSize1, aSize2, aSize3, freq); 
    cout << "builder finished" << endl; 
    cout << **(freq[1]+2) << endl; 
    destroyer(aSize1, aSize2, aSize3, freq); 
} 

私はこれをコンパイルすると、「ビルダー」機能は正常に動作しますが、私は、メイン機能で3Dアレイにアクセスしようとするたびに、私はセグメンテーションフォールトを取得します。これは私の本で読んだので、これはうまくいくと思います。何かが関数へのポインタを使って参照渡しされると、その関数はそれを操作する力を持つことになります。また、要素に正しくアクセスするためには3次元配列を3回(すなわち*** freq)逆参照する必要があると予想しましたが、コンパイラは私に怒りを吹き飛ばしてぼんやりしています。

myBuilder.cpp:42:17: error: indirection requires pointer operand ('int' invalid) cout << ***(frequencies[i1]+1) << endl;

私はこれが新しい質問ですが、助けていただければ幸いです! builderdestroyer

+5

ベアボーンCスタイルの配列や動的メモリ割り当てなどではなく、適切なC++コンテナ( 'std :: vector'、' std :: array'など)を使うことを強くお勧めします。 C++のすべての利点を捨てて、C言語でプログラミングしているかもしれません。 –

+1

* "ポインタを使って何かが参照によって渡された場合" *とそのコードビジネスの中でmanuel memory managementを使用すると、 。 –

+1

私はDietel本を使用しています。私は手動のメモリ管理を勧めていませんが、私は自分自身が不思議で、難しい例(少なくとも私にとっては)を通ることでポインタをよりよく理解したかったのです。 – Astaboom

答えて

5

frequenciesポインタはmainにおけるfreqポインタのコピーあります。したがって、builderに設定すると、mainの(初期化されていない)ポインタは変更されません。

void builder(int aSize1, int aSize2, int aSize3, int***& frequencies); 

そして間接のあなたのレベルのために、freqint***であれば、その後、freq[1]int**であることに注意してください:あなたは、参照ではなく、ポインタにしたいです。

1

builder(aSize1, aSize2, aSize3, freq);をmain()から呼び出したときには、int ***frequencies(最初からガベージ値が入っています)を渡しており、このトリプルポインタをBuilder関数呼び出し内で更新したいとします。

ビルダー機能はメモリを割り当て、

frequencies = new int** [aSize1+1]; 

したがって以下のコード行にビルダー関数呼び出しのパラメータとして渡された*** frequecnyのコピーを更新し、それは周波数ポインタの値によってコールがありますビルダー呼び出しの完了後にmain()で更新されて返されません。それにはセグメンテーションフォルトを引き起こすためにアクセスされるガベージアドレスがまだ含まれています。

周波数のアドレスを&のようにビルダー呼び出しで渡し、ビルダー関数に応じて変更する必要があります。

関連する問題