C++ のラムダ式

ここでは C++11 で C++ に導入されたラムダ式 (Lambda Expression) について簡単に説明します。

ラムダ式を使うと簡単に関数オブジェクトを作成することができます。

例えばソートを行うときの比較関数など、あちこちで使いまわすことを想定する必要がない関数なども時には必要になります。 こうしたときにラムダ式を用いて名前なしの関数を作成して使います。

コンパイラオプション

ラムダ式は C++11 標準という比較的新しい仕様で標準化されているので、 コンパイル時にはオプションを必要である場合があります。

g++ では次のように明示的に C++11 を指定します。

g++ -std=c++11 foo.cpp

Microsoft の Visual C++ では (少なくとも) バージョン 16 以降では特にオプションなしでコンパイル可能なようです。

ちなみに、話はそれますが Visual C++ では例外ハンドラの扱いに関するオプションをつけないと警告がでます。構造化例外と C++ の両方をキャッチするなら /EHa を指定してください

ラムダ式

ここではラムダ式の使い方をみてみましょう。

次の例では、ラムダ式 []() {...} で作成した関数オブジェクトを変数 f に代入しています。f(); は関数として呼び出しています。

#include <iostream>
using namespace std;

int main() {

  auto f = []() {
    cout << "Hello, world!" << endl;
  };

  f();
}
g++ -std=c++11 test1.cpp
./a.out
Hello, world!

C++ ラムダ式での変数のキャプチャ

ラムダ式の [ ] には キャプチャリスト を記述できます。次の例ではラムダ式を定義している時点の変数 i の値をキャプチャしています。このため、その後に i の値を書き換えてもラムダ式に取り込まれた値は変わりません。

#include <iostream>
using namespace std;

int main() {

  int i = 123;

  auto f = [i]() {
    cout << "f(): i = " << i << endl;
  };

  f();

  i = 999;

  f();
}

実行結果は次のようになります。

f(): i = 123
f(): i = 123

変数 i の値は f の宣言時にキャプチャされているので、その後 999 に書き換えてもキャプチャされた値は変わりません。

C++ ラムダ式の引数

ラムダ式の引数は ( ) に指定可能です。次の例では引数として int を一つ受け取ります。変数名は j としています。

#include <iostream>
using namespace std;

int main() {
  int i = 0;
  auto f = [i](int j) {
    cout << "i = " << i << endl;
    cout << "j = " << j << endl;
  };

  i = 1;
  f(i);
}
g++ -std=c++11 test.cpp
./a.out 
i = 0
j = 1

C++ ラムダ式の戻り値の指定

戻り値は -> で指定します。次の例では int 型の戻り値を返す関数オブジェクトを指定しています。

#include <iostream>
using namespace std;

int main() {
  auto f = [](int i, int j) -> int {
    return i * j;
  };

  cout << f(2, 3) << endl;
}

実行結果は次の通り。

g++ -std=c++11 lambda1.cpp
./a.out                   
6

STL の sort と組み合わせた例については、「STL の使い方 - sort」をみてください。