構成
No.1 何故この話か
No.2.1 (数値による範囲)よくあるfor文
No.2.2 (数値による範囲)範囲for文
No.3.1 (配列ポインタクラス)よくあるfor文
No.3.2 (配列ポインタクラス)範囲for文
No.4 要は
No.1 何故この話か
某ゲームプログラミングの本を読んでいたら、自分では全然使わない範囲for文が使われていました。
ぶっちゃけどういったものなのか理解していなかったので範囲for文について見つつ、色々試してたらいろいろな利点と欠点みたいのが見えてきたので
まとめてみようかと思いました。
ただ、これは自分の見解ですし、正直C++の達人の方に質問して、実際のところどうなのか知りたいぐらいなので、読むなら温かい目でお願いします。
あと、for文以外のコード部分はこうしています。
#include <iostream>
#include <vector>
class A
{
private:
int hp;
public:
A(const int t_hp) : hp(t_hp) {}
~A() {}
const int GetHP()
{
return hp;
}
};
int main()
{
return 0;
}
No.2.1 (数値による範囲)よくあるfor文
for文を勉強し始めたときに合計値とか出されると思うんですが、それをやってみるとこんな感じ。
int sum = 0;
for (int i = 0; i != 10; ++i)
{
sum += i;
}
いや、普通じゃんっていう話だけど、範囲for文だとそうはいかない。
No.2.2 (数値による範囲)範囲for文
上記の合計値を出すものですが、範囲for文では出来ません。
リファレンスの文を借りて言えば、「メンバ関数にbegin()およびend()を持つクラスであれば、何でも範囲for文の範囲として指定できる。」ということです。
一応それっぽいのを書いてみますが、赤い波線がついて実行できません。
int sum = 0;
for (auto i : 10)
{
sum += i;
}
int sum = 0;
const int num = 10;
for (auto i : num)
{
sum += i;
}
No.3.1 (配列ポインタクラス)よくあるfor文
よく使うfor文だとこんな感じだと思います。
std::vector<A*> a(10);
for (int i = 0; i != 10; ++i)
{
a.at(i) = new A(i);
}
for (size_t i = 0, n = a.size(); i < n; ++i)
{
std::cout << a.at(i)->GetHP() << "\t";
}
std::cout << std::endl;
・ループの始めと終わりの決める必要がある。
・添え字を利用することが出来る。
No.3.2 (配列ポインタクラス)範囲for文
コードにするとこんな感じだと思います。
比較のため、内容については先ほどと同じようにします。
std::vector<A*> a(10);
int ID = 0;
for (auto& ia : a)
{
ia = new A(ID++);
}
for (const auto& ia : a)
{
std::cout << ia->GetHP() << "\t";
}
std::cout << std::endl;
・順番の数値を使うなら添え字を別途用意しないといけない。
・添え字が必要なければその分作る変数が減る。
添え字を必要としないなら範囲for文の方がいいかもしれない。
ただ、範囲for文の欠点として、for文が始まるときにbeginとendを利用する形で行っているので、途中から数が増えたり減ったりしたら「イテレータが無効」となるため、エラーが起きる。
よく使う方のfor文だとイテレータ関係なく範囲を数値でやっているのでエラーにはならず普通に動きますね。
std::vector<A*> a(10);
for (int i = 0; i != 10; ++i)
{
a.at(i) = new A(i);
a.push_back(new A(i));
}
for (size_t i = 0, n = a.size(); i < n; ++i)
{
std::cout << a.at(i)->GetHP() << "\t";
}
std::cout << std::endl;
No.4 要は
添え字の数値を使う必要があるのであれば、よくあるfor文でいいかもしれないが、
添え字を必要としないなら範囲for文を使った方が添え字の無い文見やすくなるかもしれない。
ただ、調べていくうちにoperator[]を使ったりなどすれば添え字も取り出せるみたいです。
あと、範囲for文は忠実に回すので逆順が出来ないみたいです。boost使えば、なんか楽にできるみたいですが…。その他に、std::reverseを使えば配列自体が逆になるのでこれでもいいかもしれません。配列数が多い場合は良い判断とは言えないかもしれませんが。