C++において、ラムダ式は非常に便利な機能です。
この記事では、C++のラムダ式についてサンプルコードを交えながらラムダ式の基礎から応用までを解説していきます。
ラムダ式とは何か
ラムダ式とは、C++11から導入された無名関数のことです。
通常の関数と同様に、引数を受け取り、戻り値を返すことができますが、ラムダ式は名前を持たず、その場で定義されるため、「無名関数」と呼ばれます。
わざわざ名前付きの関数を定義するまでもないけど、繰り返し行う処理だから一時的に関数化したいといった場面で役立ちます。
ラムダ式の基本構文
ラムダ式は、関数を定義するような構文で書かれます。
[capture list] (parameters) -> return_type {
// 処理
}
capture list
: ラムダ式が参照する変数を指定します。省略可能です。parameters
: ラムダ式の引数を指定します。省略可能です。return_type
: ラムダ式の戻り値の型を指定します。省略可能です。
例えば、以下のようなラムダ式があります。
auto func = [](int x, int y) -> int {
return x + y;
}
このラムダ式は、2つの引数xとyを受け取り、それらを足した結果を返す関数として使われます。
通常、ラムダ式の外にある変数を使用するには引数として渡す必要がありますが、capture listにラムダ式内で使用する変数や定数を指定することで、ラムダ式内で自由に扱えるようになります。
int a = 10;
auto func = [a]() {
std::cout << "a = " << a << std::endl;
};
func();
a = 10
この場合、capture list
に[a]
と指定されているため、ラムダ式内では引数の有無にかかわらず変数a
に値渡しされたコピーを使用できるようになります。
ラムダ式の使い方
ラムダ式は、関数オブジェクトとして利用することができます。また、STLアルゴリズムやスレッド処理でも利用されます。
関数オブジェクトとしてのラムダ式
関数オブジェクトとは、関数をオブジェクト化したものです。
C++では、関数ポインタやファンクタ(関数オブジェクト)を使用することができますが、ラムダ式も関数オブジェクトとして利用することができます。
以下は、ラムダ式を使用した簡単な例です。
auto func = [](int x, int y) { return x + y; };
int result = func(1, 2); // resultには3が代入される
このように、[]
内にキャプチャ変数を指定し、引数を取る無名関数を定義することができます。上記の例では、2つの引数を受け取り、それらを加算して返す無名関数を定義し、func
に代入しています。
STLアルゴリズムでのラムダ式の利用
STLアルゴリズムでは、様々な操作が可能です。その中でも特に便利なのがラムダ式を使用した操作です。
以下は、vectorコンテナ内の要素全てに対して2倍した値を出力する例です。
std::vector<int> vec{1, 2, 3};
auto twice_f = [](int& n){ std::cout << n * 2 << " "; };
std::for_each(vec.begin(), vec.end(), twice_f);
// 出力結果: 2 4 6
このように、std::for_each()
メソッド内でラムダ式を使用することで簡単に要素全てに対して操作することができます。
スレッド処理でのラムダ式の利用
スレッド処理では、複数のスレッド間で同時に実行される処理を記述する必要があります。
その際にもラムダ式は便利なツールとなります。
以下は、スレッド処理内でラムダ式を使用した例です。
#include <iostream>
#include <thread>
void thread_func(int x)
{
std::cout << "Thread start" << std::endl;
auto func = [](int x){ return x * 2; };
int result = func(x);
std::cout << "Result: " << result << std::endl;
}
int main()
{
std::thread th(thread_func, 10);
th.join();
}
このように、スレッド処理内部でラムダ式を使用し計算結果を表示させることが出来ました。