4

静的リンケージを持つ C++ グローバル多次元配列があります。スタックが割り当てられると想定しています(標準で関連するセクションが見つかりません)。連続して割り当てられていますか?

別の質問: これらの静的グローバル n-dim 配列をヒープに割り当てられるように変換したいと考えています。コードの変更を最小限に抑えたいと考える最も簡単な方法は何ですか? 配列を n-dim ポインターに変換し、main の開始時に malloc し、main を終了する前に解放することを考えることができます。しかし、連続した割り当てについて心配する必要があります。誰かがより良い方法を見ますか?

ありがとう、

ニレッシュ。

4

3 に答える 3

2

静的リンケージを持つ C++ グローバル多次元配列があります。スタックが割り当てられると想定しています(標準で関連するセクションが見つかりません)。

スタックにはありません。グローバルエリアになります。グローバルおよび静的ストレージ オブジェクトは、ヒープやスタックの一部ではない独自のメモリ領域を取得します。

さらに、スタック (標準では「自動」ストレージと呼んでいます) オブジェクトは、それらが含まれている関数呼び出しの間のみ存続します。グローバルmain()は呼び出される前に初期化され、終了後に破棄されmain()ます。

連続して割り当てられていますか?

標準がそれを要求しているとは思えませんが、そうかもしれません。(明確化: 1 次元配列の連続ストレージは保証されていますが、2 次元以上の配列の行間に「ギャップ」がないという保証はありません。) 連続割り当てが必要な場合は、グローバル配列を 1 として宣言します。次元ベクトルを作成し、インライン関数を使用して複数の次元を対応するインデックスに変換します。これは、連続したストレージが保証されている場合にコンパイラが生成するものと同じです。

これらの静的グローバル n-dim 配列をヒープに割り当てられるように変換したいと考えています。コードの変更を最小限に抑えたいと考える最も簡単な方法は何ですか?

グローバル宣言を配列からポインターに変更します。この場合、ストレージをベクトル化することを強くお勧めします。(いいえ、私は について話しているのではなくstd::vector、1-D ベクトルへの再形成について話しているのです。)

配列を n-dim ポインターに変換することを考えることができます

そのような獣はいません。最後に、ポインターの配列へのポインターです。これは、ベクトルまたはより多くのポインターの配列のいずれかを指し、深さは次元数によって決まります。ND 座標を 1-D インデックスに変換する関数を使用すると、上記の 1-d ベクトルの場合よりもはるかに遅くなります。

main の開始時に malloc'ing し、main を終了する前に free'ing します。

これは、メモリリークを探すためにまたは同様のものをfree使用していない限り、最後に行う必要がないことを除いて. valgrindOS は、プロセスの終了時に共有メモリではないすべての割り当てを解放します。

したがって、次のようなものが得られます。

#include <stddef.h>

static const size_t kDimX = 5;
static const size_t kDimY = 20;
static const size_t kDimZ = 4;

inline size_t DimsToVector(size_t x, size_t y, size_t z)
{
    return (x * kDimY + y) * kDimZ + z;
}

float* data = 0;

int main()
{
    data = new float[kDimX * kDimY * kDimZ];

    // Read elements with: data[DimsToVector(x, y, z)]
    // Write v with: data[DimsToVector(x, y, z)] = k;

    delete[] data; // Optional.
}

operator []クラスを定義し、いくつかの醜いものを隠すためにオーバーライドする、おそらくBoostのような、より洗練された方法がありますが、これはあなたが始めるための最低限のものです.

于 2012-05-16T21:38:11.780 に答える
1

スタックに割り当てられていません。グローバル変数は、特別なメモリ セグメントに「割り当て」られます。

多次元配列を「連続」にする場合、型システムとあまり戦わずに考えることができる最も簡単な確実な方法はtypedef、より低い次元の を作成し、その型へのポインターを作成することです。

typedef int TenIntegers[10];
TenIntegers* ints;

int main()
{
    ints = new TenIntegers[50];

    // your code here
    ints[0][5] = 3;

    delete[] ints;
}
于 2012-05-16T21:22:54.023 に答える
0

1) グローバルのメモリは、「メモリ内」のどこかに割り当てられます。スタックにもヒープにもありません。たとえば、グローバル定数は通常、実行可能ファイルの読み取り専用セクションに配置されます。厳密に言えば、実装依存です。なぜこれを知る必要があるのですか?

2) メモリは連続します。

于 2012-05-16T21:29:23.920 に答える