STL で配列を繰り返し処理する - C++ プログラミング
PROGRAM
STL で配列を繰り返し処理する
C++ の STL (Standard Template Library) には、配列の要素をひとつずつ取得して繰り返し処理する関数 std::for_each が用意されています。
これを使用することで、他の言語での for each や foreach 構文のような、要素をひとつずつ順次処理する構文と似た実装を C++ でもできるようになります。
ただし使い方は少し癖があって、std::for_each の引数として、開始位置と終了位置と、各要素毎に実行する処理を関数で渡す必要があります。
必要なインクルードファイル
std::for_each 関数を使うためには algorithm ヘッダーを組み込む必要があります。
#include <algorithm>
こうすることで std::for_each を使う準備が整いました。
C 関数を使用する方法
まずは std::for_each に渡す関数を C 言語の関数を使って定義する方法です。
関数は、配列の各要素を 1 つずつ受け取って処理できる関数であればいいので、たとえば配列の要素が CMyClass 型の場合には、ヘッダーファイルのクラス定義よりも外側か、実装ファイル内で、次のようにヘッダーを定義します。
void functionForEach(const CMyClass& element);
この関数を他で使用する予定がない場合は、ヘッダーファイルへの実装ではなく、クラスの実装ファイル内に 無名名前空間 を使って定義するのが混乱しにくいと思います。
このようにして定義した関数を、次のようにして std::for_each の引数に渡します。
ここで今回、繰り返し処理を行う配列は STL の std::vector を使った CMyClass 配列を vector という名前で定義してあるものとします。
std::for_each(vector.begin(), vector.end(), ::functionForEach);
このように、今回の例であれば std::vector の開始位置 (begin) と終了位置 (end) と一緒に、開始位置から終了位置のひとつ手前までの要素に対して、functionForEach 関数を順番に実行することができます。
ここで functionForEach 関数の前に "::" という記号を付けていますが、これは今回、この関数がグローバルスコープに定義されているので、それを明示するために付けてあります。
なお、上の例では std::vector を渡しましたが、通常の C 配列を渡すこともできます。
その場合は、開始位置は配列の先頭アドレスでいいのですが、終了位置は最後の要素のひとつ先のアドレス(先頭アドレス+要素の数)を渡す必要があるところに注意します。
クラス内に定義したメソッドを渡す方法
std::for_each に渡す関数を、クラスのメソッドにしたい場合は、static で定義されたメソッドを使います。
static void functionForEach(const CMyClass& element);
クラスにこのようなメソッドを持たせることで、次のようにして std::for_each 関数を実行できます。
std::for_each(vector.begin(), vector.end(), CMyClass::functionForEach);
自分自身に定義した static メソッドの場合は、クラス名とスコープ解決演算子 (CMyClass::) は省略できます。
なお、static 指定されていないメソッドの場合、std::for_each では呼び出し元のインスタンスを指定できず、"error C2064: 1 引数を取り込む関数には評価されません。" というコンパイルエラーになるようでした。
ラムダ式を使って記述する方法
C++11 のラムダ式を使って std::for_each で実行する関数を指定することもできます。
std::for_each(vector.begin(), vector.end(), [](const CMyClass& element) { std::cout << element.toString() << std::endl; });
このようにして、各要素毎に実行する内容を関数として定義しなくても、ラムダ式で実行したい関数を直接指定できます。
[ もどる ]