web-dev-qa-db-ja.com

ポインター間の動的2次元配列

このウェブサイトの最初のタイマーなので、ここに行きます。

私はC++の初心者であり、現在、「D.S。MalikのC++ 2nd edを使用したデータ構造」という本を読んでいます。

本の中でMalikは、動的な2次元配列を作成する2つの方法を提供しています。最初の方法では、変数をポインターの配列として宣言します。各ポインターは整数型です。例.

int *board[4];

..その後、forループを使用して「列」を作成し、ポインターの配列を「行」として使用します。

2番目の方法では、ポインターへのポインターを使用します。

int **board;
board = new int* [10]; 

等.

私の質問はこれです:どちらが良い方法ですか? **メソッドは視覚化が簡単ですが、最初のメソッドはほぼ同じ方法で使用できます。両方の方法を使用して、動的な2次元配列を作成できます。

編集:上記の投稿では十分に明確ではありませんでした。私が試したコードは次のとおりです。

int row, col;

cout << "Enter row size:";
cin >> row;
cout << "\ncol:";
cin >> col;

int *p_board[row];
for (int i=0; i < row; i++)
    p_board[i] = new int[col];

for (int i=0; i < row; i++)
{
    for (int j=0; j < col; j++)
    {
        p_board[i][j] = j;
        cout << p_board[i][j] << " ";
    }
    cout << endl;
}
cout << endl << endl;

int **p_p_board;
p_p_board = new int* [row];
for (int i=0; i < row; i++)
    p_p_board[i] = new int[col];

for (int i=0; i < row; i++)
{
    for (int j=0; j < col; j++)
    {
        p_p_board[i][j] = j;
        cout << p_p_board[i][j] << " ";
    }
    cout << endl;
}
25
user2280041

2番目の方法について説明するものは、1D配列のみを提供します。

int *board = new int[10];

これは、10個の要素を持つ配列を割り当てるだけです。おそらくあなたはこのようなことを意味していました:

int **board = new int*[4];
for (int i = 0; i < 4; i++) {
  board[i] = new int[10];
}

この場合、4つのint*sを割り当て、それぞれが動的に割り当てられた10 intsの配列を指すようにします。

そのため、これをint* board[4];と比較しています。主な違いは、このような配列を使用する場合、コンパイル時に「行」の数を知る必要があることです。配列にはコンパイル時の固定サイズが必要だからです。また、int*sのこの配列を返したい場合にも問題が発生する可能性があります。配列はスコープの最後で破棄されるためです。

行と列の両方が動的に割り当てられる方法では、メモリリークを回避するためにより複雑な手段が必要になります。次のようにメモリの割り当てを解除する必要があります。

for (int i = 0; i < 4; i++) {
  delete[] board[i];
}
delete[] board;

代わりに標準コンテナを使用することをお勧めします。適切なサイズに初期化するstd::array<int, std::array<int, 10> 4>またはおそらくstd::vector<std::vector<int>>を使用する場合があります。

8

どちらの場合も、内部ディメンションは動的に指定されます(つまり、変数から取得されます)が、違いは外部ディメンションにあります。

この質問は基本的に次のものと同等です。

int* x = new int[4]; "より良い int x[4]

答えは、「配列の次元を動的に選択する必要がない限り、no」です。

このコードは、外部ライブラリの要件がほとんどなく、int **arrayの基本的な使用法を示しています。

この回答は、each配列が動的にサイズ設定されること、および動的にサイズ設定されるリーフ配列を動的にサイズ設定されるブランチ配列に割り当てる方法を示しています。

このプログラムは、STDINから次の形式の引数を取ります。

2 2   
3 1 5 4
5 1 2 8 9 3
0 1
1 3

以下のプログラムのコード...

#include <iostream>

int main()
{
    int **array_of_arrays;

    int num_arrays, num_queries;
    num_arrays = num_queries = 0;
    std::cin >> num_arrays >> num_queries;
    //std::cout << num_arrays << " " << num_queries;

    //Process the Arrays
    array_of_arrays = new int*[num_arrays];
    int size_current_array = 0;

    for (int i = 0; i < num_arrays; i++)
    {
        std::cin >> size_current_array;
        int *tmp_array = new int[size_current_array];
        for (int j = 0; j < size_current_array; j++)
        {
            int tmp = 0;
            std::cin >> tmp;
            tmp_array[j] = tmp;
        }
        array_of_arrays[i] = tmp_array;
    }


    //Process the Queries
    int x, y;
    x = y = 0;
    for (int q = 0; q < num_queries; q++)
    {
        std::cin >> x >> y;
        //std::cout << "Current x & y: " << x << ", " << y << "\n";
        std::cout << array_of_arrays[x][y] << "\n";
    }

    return 0;
}

int mainの非常に単純な実装であり、std::cinおよびstd::coutのみに依存しています。 Barebonesですが、単純な多次元配列の操作方法を示すには十分です。

0
Andrew