C++で二次元配列を動的生成する3つの方法
C++で二次元配列を動的生成するには?ということで、思いついた3つの方法
①newする
動的生成といえばnew。C言語ならmallocとかcallocにあたります
以下はint型の二次元配列をnewして使ってdeleteする方法
#include<iostream> using namespace std; int main(){ /* new */ // int*の配列を動的生成 int **arr = new int*[20]; // 配列の各要素でintの配列を動的生成 for( int i=0; i<20; i++ ){ arr[i] = new int[10]; } // 実際に配列を使ってなんやかんや arr[19][9] = 12345; cout << arr[19][9] << endl; /* delete */ // 各要素を先にdelete for( int i=0; i<20; i++ ){ delete[] arr[i]; arr[i] = 0; // ※(記事の最後の方で説明) } delete[] arr; arr = 0; // ※ return 0; }
newをすると必ずdeleteが必要になり、し忘れるとメモリリークを起こします
そんな危険性を含んでいる①、正直おすすめの方法ではありません
②STLのvectorを使う
みんな大好きSTL。C++の標準ライブラリのことです
これを使って二次元配列を動的生成してみましょう
#include<iostream> #include<vector> // vectorを使うにはこれが必要 using namespace std; int main(){ // resize関数を使って動的にサイズを変えれる vector< vector<int> > arr; arr.resize(20); // ()内の数字が要素数になる for( int i=0; i<20; i++ ){ arr[i].resize(10); } arr[19][9] = 12345; cout << arr[19][9] << endl; // deleteのような処理はデストラクタ内で行なってくれるので不要 return 0; }
①より簡単で危険性も減ります。おすすめ
③一次元配列を二次元配列のように使う
最後はこれです。とりあえずサンプルコード
#include<iostream> using namespace std; int main(){ int *arr; // [20][10]の二次元配列を生成 arr = new int[20*10]; // arr[19][9]に代入 arr[9*20+19] = 12345; // arr[19][9]の値を表示 cout << arr[9*20+19] << endl; delete[] arr; arr = 0; return 0; }
幅w,高さhの二次元配列を作りたいとき、w*hの一次元配列を生成します
そして要素[x][y]へのアクセスの際に[y*w+x]とすることで、一次元配列を二次元配列のように扱えます
vectorは使いたくないという人にはこの方法をおすすめします。①よりは単純になります
※について。余談というか補足というか
deleteした後のポインタには0を代入しておくことが望ましいです
というのも、deleteした後のポインタにはnewの時に代入されたアドレスがそのまま格納されているからです
そして、変数aをdeleteした後にnewした変数bのアドレスは変数aと同じであることがあるからです
例えば、下記のようなコード
#include<iostream> using namespace std; int main(){ int *a = new int(); cout << a << endl; // 0x381ee0(自分がテストした時はこのアドレスだった) delete a; cout << a << endl; // 0x381ee0。delete前と同じ int *b = new int(); cout << b << endl; // 0x381ee0。aと同じ *b = 0; cout << *b << endl; // 「0」と表示される *a = 100; // aをdeleteしたことを忘れて、代入すると…(これが怖いから※1の処理をしてる) cout << *b << endl; // 「100」と表示される! delete b; return 0; }
このようなことが発生し、思わぬ所でデータをぶっ壊したりします。やべぇ
そんなことがないように、使い終わったポインタには0を入れることをオススメします