配列の初期化(+配列の動的確保)について

どーもどーも、久々の更新です。

今回はJOI予選中にハマってしまったことについて書かせていただこうかと。

 

問題文は省略。

回答作成中にint配列の全要素を-1で初期化したかったから

int array[n] = {-1};

と書いたわけですが、これが間違い。

n==5;

とすると

イメージ

array[0] == -1;

array[1] == -1;

array[2] == -1;

array[3] == -1;

array[4] == -1;

現実

array[0] == -1;

array[1] == 0;

array[2] == 0;

array[3] == 0;

array[4] == 0;

ってなるらしい。

 

それを知らなかったために色々と余計な部分を確認した。

入力データも処理も確認したけどおかしくはない、となると他の部分?

と思い変数の値をすべて出力するという暴挙に。(デバッグツールっておいしいの?)

その結果、

array[0] == -1;

array[1] == 0;

array[2] == 0;

array[3] == 0;

array[4] == 0;

......えー、何々どゆこと?

これは入力データに依存しないはずだぞ?

代入(初期化)ミス?

 

という訳で検索した結果。

初期化子リストの値の数が集約型より少ない場合、集約型の残りのメンバーまたは要素は 0 に初期化されます。

 

お、おぅふ......。

いやぁ、これ知らなかったせいでループ内の処理とか入力データを延々と睨み続けるハメに......。

普段一律の値で配列初期化するときは0ばっかりで

int array[n]={0};

って書いてて、てっきり値を1つしか書かなければその値が全部代入されるのかと思ってたんです(汗)

 

なのでここのコードを

int array[n];

for(int i=0; i<n; ++i)

    array[1]=−1;

と書き換えた結果、狙い通り動いてくれた(全要素に代入してるんだから当たり前)

 

あ、あと配列ついでにもう一個、いわゆる配列の動的確保。

動的確保ってなんぞ?って人のために(雑に)説明すると、

・配列使いたい!!

・要素数は入力された値使いたい!!→コンパイル時には要素数未定、実行時に確定させたい!!

って時に使う技術。

(実際には入力以外の要因で使いたい場面もいっぱいあるだろうけど割愛、そういう場面でも使えるから安心してね!!)

 

じゃあ、ソース書くぜ!!

// array-sample1.cpp

#include <iostream>

using namespace std;

 

int main(){

    int n;

    cin >> n;

    int array[n];

    for(int i=0; i<n; ++i)

        array[i]=0;

    for(int i=0; i<n; ++i)

        cout << "array[" << i << "] ==" << array[i] << endl;

    return 0;

}

と書いたら(開発環境にも依るっぽいけど)コンパイルエラー、または実行時にエラーが出る。

環境によって動作の変わるプログラム→不安定のプログラム、を組むということでよろしくない。

なのでここのコードを

int array[n];

から

int *array = new int[n];

と書き換えちゃいます!!

int *arrayint型の配列を「示す」よ〜(配列そのものじゃないよ!!)ってやつで、

そのあとのnew int[n];int型の領域をn個確保(つまり動的確保!!)を代入するよ!!ってやつ。

......え?動的確保ってことは結局未定のまんまじゃん、って思うだろうけどそれでいいの。

newは動的確保を可能にするためのものだからこれでいいんです!!

 

で、注意としてはnewで確保した領域はdeleteで解放しなきゃいけないっていうのがあって、それの書き方は

delete array[ ];

これだけです笑

newの時と違ってarrayのサイズが決まってるから要素数は書かなくていいの。

というわけでさっきのコードを修正すると

// array-sample2.cpp

#include <iostream>

using namespace std;

 

int main(){

    int n;

    cin >> n;

    int *array = new int[n];

    for(int i=0; i<n; ++i)

        array[i]=0;

    for(int i=0; i<n; ++i)

        cout << "array[" << i << "] ==" << array[i] << endl;

    delete[ ] array;

    return 0;

}

これでOK

 

......なんか初期化より動的確保がメインになっちゃったかも(汗)

取り敢えずここまで!!

もっと詳しく知りたいって人はここ見るといいかも→C++編(言語解説) 第12章 new/delete

次回は多次元配列の動的確保について書いてみようかな

 

2014/12/14 Sun.

 

2014/12/18 Thu.

一部修正。

new[ ]で確保した領域はdeleteではなくdelete[ ]で開放しなければなりませんでした。

私のせいで勘違いしてしまった方がいらっしゃいましたら申し訳ありませんでした。