パフォーマンスがアプリケーションにとって重要な場合は、スタックとヒープのどちらを宣言するか考慮する必要がありますか?なぜこの質問が心に浮かんだのかを概説することができます。静的配列と動的配列のC/C++パフォーマンス
C/C++の配列はオブジェクトではなく、ポインタに崩壊するため、コンパイラは、提供されたインデックスを使用して要素にアクセスするポインタ演算を実行します。私の理解では、このプロシージャは、最初の次元を通過するときに、静的に宣言された配列から動的に宣言された配列へと、が異なります。
次のようにスタック上に配列を宣言する場合は、
int array[2][3] = { 0, 1, 2, 3, 4, 5 }
//In memory { row1 } { row2 }
それはメモリの連続ブロックに格納されているので、この配列は、メモリに行優先形式で格納されることになります。つまり、配列内の要素にアクセスしようとすると、コンパイラは正しい位置を確認するためにいくつかの加算と乗算を実行する必要があります。
私は、次の
int x = array[1][2]; // x = 5
を行うことをしたのであれば、コンパイラは、この式を使用します。
をI =行のインデックスj =列率n =単一の行のサイズ(ここではn個私はその要素のそれぞれにアクセスするために、この配列をループした場合、最初の要素へ= 2)
配列=ポインタが
*(array + (i*n) + j)
*(array + (1*2) + 2)
これは、手段追加の乗算ステップがインデックスごとのアクセス毎に実行される。
ヒープ上で宣言された配列では、パラダイムが異なり、多段階の解決策が必要です。注:ここでもC++ new演算子を使うことができますが、データの表現方法に違いはないと私は信じています。
int ** array;
int rowSize = 2;
// Create a 2 by 3 2d array on the heap
array = malloc(2 * sizeof(int*));
for (int i = 0; i < 2; i++) {
array[i] = malloc(3 * sizeof(int));
}
// Populating the array
int number = 0;
for (int i = 0; i < 2; i++) {
for (int j = 0l j < 3; j++) {
array[i][j] = number++;
}
}
この配列は現在動的なので、その表現は1次元配列の1次元配列です。私はアスキー画を描こうとするでしょう...
int * int int int
int ** array-> [0] 0 1 2
[1] 3 4 5
これは、もはや乗算がもはや関与していないことを意味するでしょうか?私がしていた場合、これは、次いで、アレイ上間接/ポインタ演算を行うことになる
int x = array[1][1];
以下の[1]第二列へのポインタをアクセスした後、第2の要素にアクセスするために再度これを実行します。私はこれを言って正しいですか?
ここでいくつかの文脈があります。質問に戻る。フレームをレンダリングするのに約0.016秒かかるゲームのように、鮮明なパフォーマンスが必要なアプリケーション用のコードを記述している場合は、スタックとヒープの配列の使用について2回考える必要がありますか?今では、mallocや新しい演算子を使うのに一度のコストがかかることを認識していますが、データセットが大きくなる特定の点(Big O解析のような点)では、行のメジャーを避けるためにダイナミック配列を反復する方が良いでしょう索引付け?
[2Dのメモリ割り当てを続ける](http://stackoverflow.com/a/15062765/1673391)比較 –
ため、あなたは何が何であれ、あなたはまだ主要な(というよりも、主要な列)の行をやっています。それを測定してみてください。 – doctorlove
スタックとヒープの関係は、割り当ての大きさと、データレイアウトの問題ではなく、その大きさを知るときの問題です。 Grijesh Chauhanが既に言っているように、ヒープ上に多次元静的配列と同じレイアウトを使用することができます。構文的な砂糖が得られないだけです。また、配列へのポインタの静的な配列を持つこともできます(指摘された配列はしばしば動的に割り当てられます)。 – delnan