2011-02-18 4 views
1

いくつかの固定配列と動的に割り当てられた配列を使用するC++クラスを作成しています。 おそらくコンストラクタ/ deconstructorで動的配列のためのメモリを割り当てる適切な方法について誰かが私を導くことができるかどうか、私がsegフォールトを取得しないように明示的に呼び出す必要があるかどうかは疑問でした。だからここC++のクラスの2D配列の適切なメモリ割り当て

class Network { 

    public: 
    int n_nodes; 
    int user_index[MAX_USERS]; //a fixed array 
    int adjacency_matrix[][MAX_ITEMS]; 

    //Network(int n_node, int** adjacency); //I would rather to set the element s in a function other than the constructor 
    Initializer(int n_node, int** adjacency); 
    ~Netowrk(); 
    } 

は、このクラスのための私の具体的な質問です:ここに は、私のコードの関連部分の簡易版である

1 - 私は[] []未定との2Dアレイadjacency_matrixを持つことができます初期化関数でユーザーが設定するまでの行数と列数

2 - 2D配列はどこで削除すればよいですか?それをデコンストラクタに書くべきですか?デストラクタを明示的に呼び出す必要がありますか?デコンストラクタで破壊する必要があるものは他にありますか?

+0

Dupe? http://stackoverflow.com/questions/2294338/c-2d-dynamic-array –

答えて

2

1 - ユーザがイニシャライザ機能で設定するまで、未確定の行数と列数を持つ2次元配列adjacency_matrix[][]を使用できますか?

はい。ただし、これを行う最善の方法は、配列をまったく使用することではありません。代わりに、メモリを管理するstd::vectorを使用します。これを行うには2つの方法があります。あなたが実際に要素にアクセスする[row][column]構文を使用することができるようにしたい場合は、あなたがstd::vectorの2つの次元を使用する必要があります:あなたは次元を知ったら

std::vector<std::vector<int> > adjacency_matrix; 

、あなたはそれを移入することができます

adjacency_matrix.assign(rows, std::vector<int>(columns)); 

すべての要素を含む1次元配列(またはstd::vector<int>)を使用し、を使用してインデックス(row, column)の要素にアクセスする方が簡単な場合がよくあります。この方法では、動的割り当てが少なくなります。要素にアクセスするロジックを2つのヘルパー関数にまとめることができます。

2 - 2D配列はどこで削除すればよいですか?それをデコンストラクタに書くべきですか?

std::vectorを使用する場合は、delete何もする必要はありません。それは自分自身を清める。

[destructor]を明示的に呼び出す必要がありますか?

私は[デストラクタ]に破壊する必要がある何か他のものはありますか?

理想的には、 std::vectorやスマートポインタなどの標準ライブラリのコンテナを使用する場合は、何かを整理する必要はありません。 C++で独自のリソースを管理しようとする必要はありません。この退屈な作業を実行するためのライブラリ機能があり、それらを活用する必要があります。

0

1 - 2D配列adjacency_matrix [] []は、ユーザーが初期設定関数で設定するまで、未定義の行数と列数を持つことができますか?

はいあなたはです。です。例えば:あなたあなたがstd::vector<>を使用していない理由を持っているかどうかに依存する、か否かの

int* adjacency_matrix_; 
    int* getAdjacency(int i, int j) 
    { 
     if (!adjacency_matrix_) 
      return 0; 
     else 
      return adjacency_matrix_ + i*n_nodes + j; 
    } 
    Network() 
     : n_nodes(0), 
     adjacency_matrix_(0) 
    {} 
    void Initializer(int n_node, int** adjacency) 
    { 
     adjacency_matrix_ = new int[n_nodes * n_nodes]; 
     // Copy over data. 
    } 

2 - 2D配列はどこで削除すればよいですか?それをデコンストラクタに書くべきですか? デコンストラクタを明示的に呼び出す必要がありますか? デコンストラクタで破壊する必要があるものはありますか?

削除配列演算子を使用して、デストラクタでは間違いなく無料、はい:

~Network() 
    { 
     delete [] adjacency_matrix_; 
    } 

ネットワークオブジェクト自体がスコープの外に出るときはいつでも、あなたのデストラクタが呼び出されます。明示的なデストラクタ呼び出しを行うことはめったに必要ありません。

いいえ、デストラクタは明示的に取得するものであれば明示的に解放する必要があります。

0

あなたは、私がan answer to another question

自体は良いC++の設計慣行についてでした質問に書いた例行列クラスを好むかもしれませんが、選択された例は、多次元配列でした。

0

これを行うにはいくつかの方法があります。

最も簡単な方法は、ベクターを使用することです。独自のメモリーを管理したくない場合は、これが最適です。しかし、私は自分の記憶を管理するのが好きで、時にはこの方法が遅くて扱いにくいと感じました。私は他の方法を学びました。

最速の方法は、1次元配列を割り当てて2次元配列と同じように扱うことです。次に例を示します。

int *array = new int[width*height]; 

int get_array(int column, int row) 
{ 
    return array[row*width + column]; 
} 

delete [] array; 

これは、n番目の次元に一般化することができます。

int *array = new int[w1*w2*...*wn]; 

int get_array(int i1, int i2, ..., int in) 
{ 
    return array[in*(w1*w2*...*w(n-1)) + i(n-1)*(w1*w2*...*w(n-2)) + ... + i2*w1 + i1]; 
} 

delete [] array; 

あなたは行ごとに異なる幅を有することができるようにしたい場合は、あなたがの配列を作ることができますポインタ。このソリューションは、初期化とクリーンアップには時間がかかりますが、柔軟で調整可能であり、実行時間が比較的短くなっています。あなたが間違いを犯すと、それはまた非常に危険です。

int **array = new int*[height]; 

for (int i = 0; i < height; i++) 
    array[i] = new int[width(i)]; 

その時点で、それをアクセスするために、あなたがしなければならないすべては、あなたはそれが行ずつ行う必要があり、この配列を解放するために、しかし通例

array[i][j] 

ある

for (int i = 0; i < height; i++) 
    delete [] array[i]; 

delete [] array; 

これはn次元にも一般化できます。

int **....*array = new int**...*[w1]; 

for (int i1 = 0; i1 < w1; i1++) 
{ 
    array[i1] = new int**..*[w2]; 
    for (int i2 = 0; i2 < w2; i2++) 
    { 
      array[i1][i2] = new int**.*[w3]; 
      ... 
      for (int in = 0; in < wn; in++) 
       array[i1][i2]...[in] = new int[wn]; 
    } 
} 

for (int i1 = 0; i1 < w1; i1++) 
{ 
    for (int i2 = 0; i2 < w2; i2++) 
    { 
      ... 
      for (int in = 0; in < wn; in++) 
       delete [] array[i1][i2]...[in]; 
      ... 
      delete [] array[i1][i2]; 
    } 
    delete [] array[i1]; 
} 

delete [] array; 

この種の設定では、メモリに大混乱を招く傾向があります。これらの2次元配列だけでは、幅+1の独立した配列がmallocされます。 1つの大きな配列をmallocしてインデックスを自分で見つけ出すほうが速いでしょう。

関連する問題