web-dev-qa-db-ja.com

C ++の2D動的メモリ割り当て配列

数日前、私はインターネットから2D割り当てメモリアレイの作成について学びました。それは完璧に機能します。配列にアクセスするには、単に_matrix[i][j]_を使用しますが、入力やその他のメソッドに_*_の代わりに_[]_表記を使用して、この2D配列を逆参照できる方法はありますか?

最初の質問が解決されました*(*(matrix + i) + j)を使用できます

別の質問があります。最後のコードセグメントは割り当てられたメモリを解放することです(インターネットからも取得しました)が、理解できません。なぜ_delete [] matrix_を使用できないのですか?

_int **matrix;

// dynamically allocate an array
matrix = new int *[row]; 
for (int count = 0; count < row; count++)
{
    matrix[count] = new int[col];
}

// input element for matrix
cout << endl << "Now enter the element for the matrix..."; 
for (int i=0; i < row; i++) 
{
    for (int j=0; j < col; j++)
    {
        cout << endl << "Row " << (i+1) << " Col " << (j+1) << " :";
        cin >> matrix[i][j]; // is there any equivalent declaration here?
    }
}

// free dynamically allocated memory
for( int i = 0 ; i < *row ; i++ )
{
    delete [] matrix[i] ;   
}
delete [] matrix ;
_
6
Casper

_a[b]_は単なる*(a + b)なので、もちろんこれを行うことができます。

_*(*(matrix + i) + j)
_

とにかく、それらのnew割り当てはエラーが発生しやすいです。ネストされたnewsのいずれかがスローされると、リークが発生します。代わりに_std::vector_を使用してみてください。

3
Pubby

2番目の質問への回答:次のコードで2D配列を割り当てる場合

// dynamically allocate an array
    matrix = new int *[row]; 
    for (int count = 0; count < row; count++)
        matrix[count] = new int[col];

実際には、ポインタの1つの配列(ダブルポインタである行列変数)と整数の「行」配列(それぞれが行列内の1つの行を表し、サイズは「col」)を割り当てています。これらはmatrix[0]matrix[1]、などmatrix[row-1]まで。

したがって、マトリックスを解放する場合は、最初にすべての行(ループ内で割り当てられた配列)を解放し、次に行を保持していた配列を解放する必要があります。あなたの場合、マトリックスを解放するために使用するコードは部分的に間違っており、次のようになっているはずです。

// free dynamically allocated memory
for( int i = 0 ; i < row ; i++ )
{
    //first we delete each row
    delete [] matrix[i] ;
}
//finally, we delete the array of pointers
delete [] matrix ;

ループ内の削除はマトリックスの各行を解放し、最後の削除は行の配列を解放します。コードでは、ダブルポインタ(row)でdelete matrix回使用しますが、これは意味がありません。

最後に、ダブルポインタでシングルデリートを使用するのは間違っています。各行に割り当てられたメモリを解放せず、それを参照するポインタだけが解放されるため、メモリリークが発生するためです。

5
JBL

このようなものが機能します:

int **matrix;

// dynamically allocate an array
matrix = new (std::nothrow) int *[row];
if (matrix == NULL)
{
      // handle the error
}
for (int count = 0; count < row; count++)
{
    *(matrix + count) = new (std::nothrow) int[col];
    if (matrix[count] == NULL)
    {
          // handle the error
    }
 }

cout << "\nNow enter the element for the matrix..."; 
for (int i=0; i < row; i++)
{
    for (int j=0; j < col; j++)
    {
        cout << "\nRow " << (i+1) << " Col " << (j+1) << " :";
        cin >> *(*(matrix + i) + j);
    }
}
2
SeedmanJ

はい、ポインタ加算を使用しますが、メモリがどのように配置されているかを理解する必要があります。 xがintの配列の最初の要素へのポインタであるとすると、x [2]にアクセスする場合は、*(x + 2)を使用できます。ただし、マトリックスを使用すると、かなり混乱する可能性があり、これを行うと、マトリックス内の間違ったインデックスにアクセスする可能性が非常に高くなるため、お勧めしません。

1
mlstudent

*(*(matrix+i)+j)を実行できます。角かっこ表記と同等である必要があります。両方の表記で起こっていることは、単純にポインタ演算です。

0
Victor Zamanian