第2回は範囲に基づくfor文です。
配列、コンテナ(vectorとかの事)に対して初期化や値を利用する場合、従来では
1: #include <iostream> 2: #include <vector> 3: 4: using namespace std; 5: 6: int main() 7: { 8: int arr[5]; //固定長配列 9: vector<int> vec; //可変長配列 10: 11: int size = sizeof(arr) / sizeof(arr[0]);//固定長配列の長さを求める 12: 13: //arrの初期化 14: for (int i = 0; i < size; i++) 15: { 16: arr[i] = i; 17: } 18: 19: //vecに値を入れる 20: vec.push_back(1); 21: vec.push_back(2); 22: vec.push_back(3); 23: 24: //arrの値を表示 25: for (int i = 0; i < size; i++) 26: { 27: cout << arr[i] << endl; 28: } 29: 30: //イテレータを利用したvecの値の表示 31: auto it = vec.begin(); 32: while (it != vec.end()) 33: { 34: cout << *it << endl; 35: it++; 36: } 37: 38: return 0; 39: }
のように書きます。(よね?)
for文を使う時は
for(初期化; 終了条件; 更新){処理}
ですが、長さが分かりきってる配列の全体を利用する時に、律儀に書くのは面倒です。
修正方法として、<algorithm>のfor_eachを利用することによって
1: #include <iostream> 2: #include <vector> 3: #include <algorithm> 4: 5: using namespace std; 6: 7: //int型の配列の表示用 8: struct CPrint 9: { 10: void operator()(int value) 11: { 12: cout << value << endl; 13: } 14: }; 15: 16: int main() 17: { 18: int arr[5]; //固定長配列 19: vector<int> vec; //可変長配列 20: 21: int size = sizeof(arr) / sizeof(arr[0]);//固定長配列の長さを求める 22: 23: //arrの初期化 24: for (int i = 0; i < size; i++) 25: { 26: arr[i] = i; 27: } 28: 29: //vecに値を入れる 30: vec.push_back(1); 31: vec.push_back(2); 32: vec.push_back(3); 33: 34: //arrの表示 35: int* it1 = arr; 36: int* it2 = arr + size; 37: for_each(it1, it2, CPrint()); 38: 39: //vecの表示 40: for_each(vec.begin(), vec.end(), CPrint()); 41: 42: return 0; 43: }
表示方法の部分が固定長配列、可変長配列のどちらも同様の書き方が出来ます。
しかし、for_eachの第三引数用の関数を定義する必要があったり、固定長配列ではコンテナのbegin()、end()に相当するポインタを書く必要があり、
あまり効率が上がったとは言えません。(関数定義についてはC++11で解決出来ますが...)
そこで、C++11では範囲に基づくfor文というものが出ました。文法は
for(変数 : 配列){処理}
になります。(間のは";"ではなく、":"なのに注意)
このfor文は、固定長、可変長にかかわらず配列の長さに応じて自動的にループ処理を行ってくれます。
これで最初のプログラムを書き直すと
1: #include <iostream> 2: #include <vector> 3: 4: using namespace std; 5: 6: int main() 7: { 8: int arr[5]; //固定長配列 9: vector<int> vec; //可変長配列 10: 11: //arrの初期化 12: int i = 0; 13: for (int& num : arr)//変数部分に参照を使用することによって値の書き換えも対応出来る! 14: { 15: num = i; 16: i++; 17: } 18: 19: //vecに値を入れる 20: vec.push_back(1); 21: vec.push_back(2); 22: vec.push_back(3); 23: 24: //arrの表示 25: for (int i : arr) 26: { 27: cout << i << endl; 28: } 29: 30: //vecの表示 31: for (int i : vec) 32: { 33: cout << i << endl; 34: } 35: 36: return 0; 37: }
このように、固定長配列、可変長配列のどちらでも同じ書き方が出来る+わざわざイテレータやsizeof等を使用して長さを管理しなくてよくなります。
何より、書く量が少なくなり、作業効率、可読性があがるのがいいです。
ぜひ使うようにしてください。
以上で範囲for文の説明を終わります。