4

「new」演算子を使用して 2 次元配列を宣言するにはどうすればよいですか? 私の本にはこう書かれています。

int (*p)[4];
p=new[3][4];

しかし、それは私には意味がありません。p は 4 つの int の配列へのポインターですが、どうすれば 2 次元配列を指すようにできますか?

4

5 に答える 5

10

ポインタからポインタへのポインタが必要なようです。編集: より正確に言うと、次の例では、 arrays へのポインターの配列を作成します。

最初に行うこと:

int **p = new int*[NUM];

ここで、ポインターの配列を作成しました。ここで、それらすべてに対して別の配列を作成する必要があります。この方法でできること:

for(int i = 0; i < NUM; i++)
{
    p[i] = new int[ANOTHER_NUM];
}

解放の場合も同様ですが、逆の方法で行います。

for(int i = 0; i < NUM; i++)
{
    delete[] p[i];
}

そして最後に:

delete[] p;

これで作業できます。このようにして、「*」を追加するだけで、N 次元配列を作成できます。他に特定の質問がある場合は、コメントで質問してください。

ただし、一般的に、詳細については、「C++ の 2D 配列」や「2D 配列 C++ の動的割り当て」などの質問で Google を試すことをお勧めします。つまり、このクエリです。

于 2012-04-08T12:14:07.417 に答える
5

int他の答えは、行ごとの配列へのポインターを使用して、行のポインター配列を持つことをカバーしています。別のオプションは、すべての 2 次元配列の要素を保持するのに十分な大きさの 1 次元配列を単純に割り当てることです。

int* p = new int [3 * 4];

p[r][c]次に、構文を使用する代わりに、を使用しますp[r * kNumCols + c]。この例では、kNumCols = 4. これは通常、LAPACK スタイルの数値計算で行われることです。これは、メモリ内で連続したものを保持し、それほど多くのメモリ ブロックを割り当てる必要がないためです。

注: これは、一般的に、行オフセットの計算が一般的な部分式の最適化によってループの外に移動されるため、実際には別の方法よりも遅くはありません。また、多くのオプティマイザーは、このパターンを探すことを知っています。さらに、データを 1 つのメモリ ブロックに同じ場所に配置することで、データがキャッシュに残る可能性が高くなります。

p[][]C++ では、ヘルパー テンプレート クラスを使用して表記を実装できます。

template<class T>
class Array2DPtrRow
{public:
    Row(T* row_): row(row_) {}
    operator T*() { return row; }
    T& operator [](size_t c) { return row[c]; }
private:
    T* row;
};

template<class T, size_t NC>
class Array2DPtr
{public:
    Array2DPtr(T* buf_): buf(buf_) {}
    operator T*() { return buf; }
    Array2DPtrRow<T> operator [](size_t r)
        { return Array2DPtrRow<T>(buf + NC * r); }
private:
    T* buf;
};

[][]これにより、上記と同じコードに最適化されますが、表記法を使用できるようになり、コンパイル時に配列の次元を知る必要があります。使用例:

Array2DPtr<int, 4> p(new int[3 * 4]);
p[1][2];

これを変換して、NC をテンプレート パラメーターではなくクラス メンバーにすることができますが、最終的なオブジェクトは単なるポインターではなくなります。

template<class T>
class Array2DPtr
{public:
    Array2DPtr(T* buf_, size_t nc_): buf(buf_), nc(nc_) {}
    operator T*() { return buf; }
    Array2DPtrRow<T> operator [](size_t r)
        { return Array2DPtrRow<T>(buf + nc * r); }
private:
    T* buf;
    size_t nc;
};

Array2DPtr<int> p(new int[3 * 4], 4);
p[1][2];

これらのクラスは、コピー コンストラクター、代入演算子、またはデストラクターを必要としないことに注意してください。これらのクラスは、通常のポインターと同様に、ポイント先のメモリの所有権を取得しないためです。したがって、メモリを解放するには、次のことを行う必要があります。

delete[] p;

または、コンパイラがそれを理解できない場合:

delete[] (int*)p;
于 2012-04-08T12:17:09.147 に答える
3

実際に質問に答えるには:

配列は、配列の最初の要素へのポインターと同等であることを思い出してください。たとえば、次のように記述できます。

char str[14] = "Hello, world!";
char *ptr = str;

これは、2 次元配列でも機能します。

int (*p)[4];

2 次元配列の最初の要素へのポインターを宣言します。p2 番目の次元が 4 である限り、任意の 2 次元配列を指すことができるため、たとえば次のように記述できます。

int arr[3][4];
int (*p)[4] = arr;

もちろん、メモリを動的に割り当てることもできます。

int (*p)[4] = new int[3][4];

繰り返しますが、2 番目の次元は 4 でなければなりませんが、最初の次元は変更できます。

于 2012-04-08T21:37:08.787 に答える
2

C で多次元配列を宣言するには、いくつかの方法があります。

p2D 配列として明示的に宣言できます。

int p[3][4];  // All of p resides on the stack.

( newC++ を使用していて、それらをヒープに割り当てたい場合を除き、ここでは基本型には必要ないことに注意してください。)

または、ポインタのベクトル (1D 配列) として宣言し、各ベクトルにメモリを割り当てることができます。

int *p[3];                         // The vector addresses reside on the stack.
for (int i=0; i<3; i++) {
  p[i] = malloc(4 * sizeof(int));  // Each element resides on the heap.
}

// You can now access p as p[j][k] as if it were a 2D array.

for (int i=0; i<3; i++) {
  free p[i];
}

または、どちらの次元もわからない場合は、2D 配列全体を動的に割り当てることができます。

#define WIDTH 3
#define HEIGHT 4
int **p;                              // Base address resides on the stack.

p = malloc(WIDTH * sizeof(int *));    // Pointers to vectors reside on the heap.
for (int i=0; i<WIDTH; i++) {
  p[i] = malloc(HEIGHT * sizeof(int)); // Data values reside on the heap.
}

// You can now access p as p[j][k] as if it were a 2D array.

// Release the memory that was allocated to each vector.
for (int i=0; i<WIDTH; i++) {
  free(p[i]);
}
// Release the memory that was allocated to the initial pointer.
free(p);
于 2012-04-08T12:10:06.837 に答える
1

このようなものが必要です

int **array_ptr; //two * are needed because it is a pointer to a pointer

array_ptr=new int*[firstnumber]; //creates a new array of pointers to int objects

for(int i=0; i<firstnumber; ++i)
array_ptr[i]=new int[secondnumber];
于 2012-04-08T12:09:38.277 に答える