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; });

このようにして、各要素毎に実行する内容を関数として定義しなくても、ラムダ式で実行したい関数を直接指定できます。


[ もどる ]