2017-07-14 13 views
1

int**で宣言された2次元整数配列を初期化して変更する正しい構文はC++でですか?C++の関数内の2次元配列の値を変更

私は以下のコードを使用していますが、関数の終了時にメモリが割り当て解除されるため予期しない動作が発生します。

しかし、これはC++でどのようにうまくいくのでしょうか?私は他の人が同様の問題に直面していることを知っていますが、Is passing pointer argument, pass by value in C++?のような質問はあまりにも一般的です。

void Insert_into_2D_Array(int** foo, int x_pos, int y_pos, int x_size, int y_size) 
{ 
    int insert_value = 10; 

    if (x_pos < x_size && y_pos < y_size) { 
    foo[x_pos][y_pos] = insert_value; // insert_value lost post func exit? 
    } 
} 

void Init_2D_Array(int** foo, int x_size, int y_size) 
{ 

    foo = new int*[x_size]; // new alloc mem lost post func exit ? 
    for (int i=0;i<x_size;i++) 
    { 
     foo[i] = new int[y_size];  // new alloc mem lost post func exit 
    } 
} 

int main(int agc, char** argv) 
{ 

    int** foo; 
    int x_size=10, y_size=10; 
    Init_2D_Array(foo, x_size, y_size); 
    Insert_into_2D_Array(foo, 3,3, x_size, y_size); 

} 
+0

「new」を呼び出すと、関数が返ってもメモリは割り当て解除されません。 – user463035818

+0

割り当てが解除されていません。単にポインタ 'foo'の値を設定するだけです。これは渡される*値*です。ローカルで 'foo'を宣言するか、' int *** foo'を渡して最後に参照解除する必要があります。 – meowgoesthedog

+0

Doing 'Init_2D_Array(foo)'はあなたが言っているようにそれを値渡しします。参照渡しするには、構文はどうすればよいですか? –

答えて

1

as undercore_dが推奨されていますが、正しい方法はstd :: vectorを使用して参照を渡すことです。

しかし、あなたはまだあなたのコードのようにポインタを使用したい場合は、ここで

if (x_pos < x_size && y_pos < y_size) { foo[pos] = insert_value; // insert_value lost post func exit }

私のために働いていたコードは次のとおりです。すべての

void Insert_into_2D_Array(int** foo, int x_pos, int y_pos, int x_size, int y_size) 
{ 
    int insert_value = 10000; 

    if (x_pos < x_size && y_pos < y_size) { 
    (foo)[x_pos][y_pos] = insert_value; // insert_value lost post func exit 
    } 
} 

void Init_2D_Array(int*** foo, int x_size, int y_size) 
{ 

    *foo = new int*[x_size]; // new alloc mem lost post func exit 
    for (int i=0;i<x_size;i++) 
    { 
     (*foo)[i] = new int[y_size];  // new alloc mem lost post func exit 
    } 
} 

void main(){ 

     int** foo = NULL; 
     int x_size=10, y_size=10; 
     Init_2D_Array(&foo, x_size, y_size); 
     Insert_into_2D_Array(foo, 3,3, x_size, y_size); 

     cout<<"############# "<<foo[3][3]<<endl; 
} 
+0

関数のパラメータで 'int ** foo'でなければなりませんか? –

+0

@dr_rkはいそれはint **のようにすべきです** foo ..悪いコピーによって...!今変わる! – AdityaG

1

spugが言ったように、メモリは割り当てが解除されていないので、ポインタを失うだけです。あなたが参照することにより、それを渡す必要があります。

void Init_2D_Array(int** & foo, int x_size, int y_size) 

あなたない限り、私はC++での多次元配列を使用したことがないお勧めします本当にはポインタへのポインタが必要です。より簡単で安全な方法は、サイズがx*yの1次元配列の周りにラッパークラスを作成し、xyの座標を指定することで、基底の要素にアクセスできるようにする関数または演算子を定義することです。

class Array2D 
{ 
private: 
    int* m_array; 
    int m_sizeX; 
    int m_sizeY; 

public: 
    Array2D(int sizeX, int sizeY) : m_sizeX(sizeX), m_sizeY(sizeY) 
    { 
     m_array = new int[sizeX*sizeY]; 
    } 

    ~Array2D() 
    { 
     delete[] m_array; 
    } 

    int & at(int x, int y) 
    { 
     return m_array[y*sizeX + x]; 
    } 
}; 

このソリューションは、複数のキャッシュに優しい直線と密に充填された内容を格納することによって、あることの付加的な利点を持っています。

1

まず、 2D配列やその他の多次元配列の場合は、1次元バッファをストレージとして使用し、項目をy * width + xとして扱う方がよい。

しかし、あなたが本当にそれを使用したい場合は、いくつかの問題があなたの特定の場合には、いくつかの問題。 固定コードがあります。まず最初に、init関数では新しい割り当てポインタを取得しません。関数とアドレスに渡すと、関数に渡したアドレスと同じアドレスが返されます。新しい割り当てられたアドレスは失われます。

void Insert_into_2D_Array(int** foo, int x_pos, int y_pos, int x_size, int y_size) 
{ 
    int insert_value = 10; 

    if (x_pos < x_size && y_pos < y_size) { 
     foo[x_pos][y_pos] = insert_value; // insert_value lost post func exit 
    } 
} 

int** Init_2D_Array(int x_size, int y_size) 
{ 

    int** foo = new int*[x_size]; // new alloc mem lost post func exit 
    for (int i = 0; i<x_size; i++) 
    { 
     foo[i] = new int[y_size];  // new alloc mem lost post func exit 
    } 

    return foo; 
} 

int main() 
{ 

    int** foo; 
    int x_size = 10, y_size = 10; 
    foo = Init_2D_Array(x_size, y_size); 
    Insert_into_2D_Array(foo, 3, 3, x_size, y_size); 

    return 0; 
} 
+0

'foo [x_pos] [y_pos] = insert_value;'は配列の値を設定し、関数が終了しても失われないことを確信していますか? –

+0

はい。 debbugerで試したり、実行後に結果を表示することができます。挿入時にバッファはすでに割り当てられています。関数fooのアドレスを関数Insert_into_2D_Arrayに渡し、最後に同じアドレスを使用します。また、insert_positionの値を代入するので、関数exitの後にこの変数が破棄されるので問題はありません。 –