少なくとも 2 つのオプションがあります。より簡単な方法は、インデックス計算の複雑さを隠すプリプロセッサ マクロを宣言することです。次に例を示します。
#define ARR(A,i,j,k) A[(i)*ylength*zlength+(j)*zlength+(k)]
ARR(myarray,i,j,k) = ARR(myarray,i+1,j,k) + ARR(myarray,i,j+1,k) + ...
これは扱いにくいです。なぜなら、マクロは先頭の次元が固定された配列 ( x ylength
xなど) でしか機能しないからzlength
です。
それを行うためのより良い方法は、いわゆるドープベクターを使用することです。ドープ ベクトルは基本的に大きな配列へのインデックスです。実際のデータを保持するために 1 つの大きなフラット チャンクを割り当てxlength * ylength * zlength
てから、インデックス ベクトル (実際には 3D の場合はツリー) を作成します。あなたの場合、インデックスには2つのレベルがあります:
xlength
へのポインタで構成されるトップレベル
- 第 2 レベル。
xlength
ポインターの配列で構成され、それぞれがメモリ内の要素ylength
のブロックの先頭へのポインターを含みます。zlength
最上位のポインター配列を呼び出しましょうA
。次に、データの - 番目のスラブA[i]
を記述するポインター配列へのポインターです。は( 3D 配列の場合)を指す - 番目のポインター配列の - 番目の要素です。ドープ ベクトルの構築は、次のように機能します。i
A[i][j]
j
i
data[i][j][0]
data
double *data = new double[xlength*ylength*zlength];
double ***A;
A = new double**[xlength];
for (int i = 0; i < xlength; i++)
{
A[i] = new double*[ylength];
for (int j = 0; j < ylength; j++)
A[i][j] = data + i*ylength*zlength + j*zlength;
}
ドープ ベクトルは、通常の配列と同じくらい簡単に使用できますが、いくつかの特別な考慮事項があります。たとえばA[i][j][k]
、 の目的の要素にアクセスできますdata
。ドープ ベクトルの 1 つの注意点は、トップ レベルが他のポインター テーブルへのポインターで構成され、データ自体へのポインターではないため、 のショートカットとして使用したり、A
のショートカットとして使用したりできないことです。Stillは と同等です。もう 1 つの注意点は、この形式の配列のインデックス付けは、ポインターの追跡を伴うため、通常の 3D 配列のインデックス付けよりも遅いということです。&A[0][0][0]
A[i]
&A[i][0][0]
A[i][j]
&A[i][j][0]
一部の人々は、データとドープ ベクトルの両方に 1 つのストレージ ブロックを割り当てる傾向があります。割り当てられたブロックの先頭にインデックスを配置するだけで、実際のデータはその後に続きます。この方法の利点は、配列の破棄がメモリ ブロック全体を削除するのと同じくらい簡単であることです。一方、前のセクションのコードで作成されたドープ ベクトルを破棄するには、free
オペレーターを複数回呼び出す必要があります。