「new」演算子を使用して 2 次元配列を宣言するにはどうすればよいですか? 私の本にはこう書かれています。
int (*p)[4];
p=new[3][4];
しかし、それは私には意味がありません。p は 4 つの int の配列へのポインターですが、どうすれば 2 次元配列を指すようにできますか?
「new」演算子を使用して 2 次元配列を宣言するにはどうすればよいですか? 私の本にはこう書かれています。
int (*p)[4];
p=new[3][4];
しかし、それは私には意味がありません。p は 4 つの int の配列へのポインターですが、どうすれば 2 次元配列を指すようにできますか?
ポインタからポインタへのポインタが必要なようです。編集: より正確に言うと、次の例では、 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 を試すことをお勧めします。つまり、このクエリです。
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;
実際に質問に答えるには:
配列は、配列の最初の要素へのポインターと同等であることを思い出してください。たとえば、次のように記述できます。
char str[14] = "Hello, world!";
char *ptr = str;
これは、2 次元配列でも機能します。
int (*p)[4];
2 次元配列の最初の要素へのポインターを宣言します。p
2 番目の次元が 4 である限り、任意の 2 次元配列を指すことができるため、たとえば次のように記述できます。
int arr[3][4];
int (*p)[4] = arr;
もちろん、メモリを動的に割り当てることもできます。
int (*p)[4] = new int[3][4];
繰り返しますが、2 番目の次元は 4 でなければなりませんが、最初の次元は変更できます。
C で多次元配列を宣言するには、いくつかの方法があります。
p
2D 配列として明示的に宣言できます。
int p[3][4]; // All of p resides on the stack.
( new
C++ を使用していて、それらをヒープに割り当てたい場合を除き、ここでは基本型には必要ないことに注意してください。)
または、ポインタのベクトル (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);
このようなものが必要です
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];