web-dev-qa-db-ja.com

多次元配列への動的ポインターを初期化する正しい方法は?

ダイナミックポインターを2次元以上の範囲に配置すると、運が悪かった。たとえば、2D配列へのポインターが必要です。そんなこと知ってる:

int A[3][4];
int (*P)[4] = A;

完全に合法です(理由を完全に理解していなくても)。以下を考慮に入れて:

int *P = new int[4];

動作し、私はそれを想像した:

int **P = new int[5][7];

動作しますが、動作しません。このコードはエラーを示します:

Error: A value of type "(*)[7]" cannot be used to initialize an entity of
       type "int **"

これを見ると、新しい部分は、私が作成した7つの整数の配列へのポインターになります。

int (*P)[4] = new int[7][4];

そして、これは機能しますが、私が達成したいことではありません。そのようにすることで、少なくとも後続のディメンションに定数値を使用することに制限されますが、実行時に完全に定義されるため、「動的」になります。

この多次元ポインターを機能させるにはどうすればよいですか?

26
Jader J Rivera

いくつかの基本的な例から始めましょう。

あなたが言う時 int *P = new int[4];

  1. new int[4];は演算子new function()を呼び出します
  2. 4つの整数にメモリを割り当てます。
  3. このメモリへの参照を返します。
  4. この参照をバインドするには、戻り参照と同じタイプのポインターが必要です。

    int *P = new int[4]; // As you created an array of integer
                         // you should assign it to a pointer-to-integer
    

多次元配列の場合、ポインターの配列を割り当ててから、次のように配列へのポインターでその配列を埋める必要があります。

int **p;
p = new int*[5]; // dynamic `array (size 5) of pointers to int`

for (int i = 0; i < 5; ++i) {
  p[i] = new int[10];
  // each i-th pointer is now pointing to dynamic array (size 10)
  // of actual int values
}

これは次のようなものです。

enter image description here

メモリを解放するには

  1. 一次元配列の場合、

     // need to use the delete[] operator because we used the new[] operator
    delete[] p; //free memory pointed by p;`
    
  2. 2D配列の場合、

    // need to use the delete[] operator because we used the new[] operator
    for(int i = 0; i < 5; ++i){
        delete[] p[i];//deletes an inner array of integer;
    }
    
    delete[] p; //delete pointer holding array of pointers;
    

メモリリークとぶら下がりポインタ!を避けてください!

68
Dipak Ingole

次のようなものが必要です:

int **P = new int*[7];
p[0] = new int[5];
p[1] = new int[5];
...
6
Paul Evans

別のアプローチは、1D配列を2D配列として使用することです。この方法では、メモリを1回(1つの連続したブロック)割り当てるだけで済みます。

int *array;
size_t row=5,col=5;
array = (int*)malloc(row*col*sizeof(int)) //or new int[row*col]

これは、「int array [5] [5]」と同じ結果になります。

行うフィールドにアクセスするには:

array[1 //the row you want
 * col //the number of columns
+2//the column you want
] = 4;

これは次と等しい:

array[1][2];
2
the baconing

これにより、一部のデバッグコンパイラで境界チェックが実行され、動的サイズが使用され、自動的に削除されます。唯一の落とし穴はxとyです。

std::vector<std::vector<int>> array2d(y_size, std::vector<int>(x_size));

for (int y = 0; y < y_size; y++)
{
    for (int x = 0; x < x_size; y++)
    {
        array2d[y][x] = 0;
    }
}
2
Neil Kirk