C++ のラムダ関数

Anam Javed 2023年10月12日
  1. C++ での Lambda 関数の構文
  2. C++ で通常の関数ポインターを使用して Lambda 関数を実装する
  3. C++ で std::function を使用して Lambda 関数を実装する
  4. C++ で auto を使用して Lambda 関数を実装する
  5. C++ での Lambda 関数の使用
C++ のラムダ関数

この記事では、関連する例とともに、C++ での Lambda 関数の構文と実装について詳しく説明します。

C++ では、Lambda 関数、つまり無名関数は、別の関数内で匿名で定義されます。ソースコードにインラインで記述され、呼び出し可能なオブジェクトを受け取る別の関数に引数として渡されます。

これにより、C++ プログラマーは関数を簡単かつ迅速に作成できます。これらの関数には名前がなく、再利用されません。

C++ での Lambda 関数の構文

一般的な構文:

[Capture List](Parameter List) { Function Body; }

Capture List は、ラムダ関数が作成されたことをコンパイラに通知します。

関数本体内で変数を使用するには、まず、キャプチャリスト内で変数をキャプチャする必要があります。そうしないと、関数本体の範囲外になります。

キャプチャされた変数は、コピーまたは参照としてアクセスできます。変数をキャプチャすることは、通常の関数で引数を渡すこととは見なされません。

ここで、a は値によってキャプチャされます。

auto f = [a]() { return a * 9; };

そしてここで、a は参照によってキャプチャされます:

auto f = [&a]() { return a++; };

パラメータリストは、その名前が示すように、通常の関数のように引数を取ります。渡される引数がない場合は、書き込みはオプションです。

() がある場合:

auto call_foo = [x]() { x.foo(); };

() がない場合:

auto call_foo2 = [x] { x.foo(); };

上記のこれらのラムダ関数は両方とも同じ意味を持っています。

関数本体には、他の通常の関数と同じように実行されるコードが含まれています。

int mul = 5;
auto ans = [mul](int a) { return a * mul; };
std::out << ans(2);

出力:

5

C++ での Lambda 関数の例:

#include <iostream>
#include <string>
using namespace std;

int main() {
  auto sum = [](int a, int b) { return a + b; };
  cout << "Sum of two integers:" << sum(5, 5) << endl;
  return 0;
}

出力:

Sum of two integers: 10

auto キーワードを使用して、パラメーターのデータ型が実行時に決定されることを示しました。これについては、次のセクションでさらに説明します。

C++ で通常の関数ポインターを使用して Lambda 関数を実装する

関数ポインターを使用して、C++ でラムダ関数を実装できます。

int main() {
  double (*addNum1)(double, double){[](double a, double b) { return (a + b); }};
  addNum1(1, 2);
}

出力:

3

ここで、*addNum1 は、空のキャプチャ句でのみ機能する標準の関数ポインタです。その後、パラメータのタイプが宣言されます-doubledouble

これは関数プロトタイプと呼ばれます。コンパイラ用に Lambda 関数が作成されたことを示す空のキャプチャ句を確認できます。

さらに、パラメータリストには double adouble b の 2つの変数が渡されます。そして、関数本体の内部で、これらの変数の加算が返されます。

main 関数が閉じられた後、関数 addNum(1,2) が呼び出され、出力として 3 が返されます。

C++ で std::function を使用して Lambda 関数を実装する

std::function addNum{[](double a, double b) { return (a + b); }};
addNumbers2(3, 4);

出力:

7

std::function は、ラムダ関数をパラメーターおよび戻り値として渡します。テンプレートで引数リストと戻り値の正確な型を宣言できます。

ここでは、2つの変数 double adouble b がパラメータリストに渡されます。そして、関数本体の内部で、これらの変数の加算が返されます。

main 関数が閉じられた後、関数 addNum(1,2) が呼び出され、出力として 7 が返されます。

C++ で auto を使用して Lambda 関数を実装する

auto addNum{[](double a, double b) { return (a + b); }};
addNum(5, 6);
return 0;

出力:

11

ラムダには型がないため、ラムダを直接使用することはできません。その結果、ラムダ関数を作成すると、コンパイラーは一意のタイプのパラメーターを作成します。

ラムダ関数のタイプはわかりませんが、定義後に使用できるように保存する方法は多数あります。ラムダの実数型を使用する唯一の方法は、auto を使用することです。

Lambda 関数は、auto として宣言した後、C++ プログラムのどこでも使用できます。

C++ での Lambda 関数の使用

ラムダ式は通常、アルゴリズムをカプセル化して別の関数に渡すために使用されます。

ラムダ関数は、定義の直後に実行できます:[ ](double a, double b)

{return (a + b)}();  // immediately executed lambda expression
{ return (a + b) }  // simple code block

ご覧のとおり、ラムダ式は複雑な関数を再構築するための効果的なツールです。

次に、明示的なパラメータ化のプロセスを段階的に実行し、その間に中間テストを行うことができます。コードブロックが適切にパラメータ化されたら、それを外部の場所に再配置し、通常の機能にします。

Lambda 式を使用すると、名前付きのネストされた関数を作成することもできます。これにより、不要なロジックを削除できます。自明でない関数を別の関数のパラメーターとして指定する場合、名前付きラムダを使用する方が目には簡単です。

auto algo = [&](double x, double m, double b) -> double { return mx + b; };
int l = algorithm(1, 2, 3), m = algorithm(4, 5, 6);
ノート
ラムダは汎用であり、すべてのデータ型に使用できます。

関連記事 - C++ Lambda