C++ラムダ式の使い方と実践例

ラムダ式は、C++11以降で導入された機能であり、関数オブジェクトを簡潔に定義できる仕組みです。特にmain関数内でのローカル関数定義や、グローバル変数の乱用を避けたい場面で非常に有用です。

基本構文

auto lambda = [capture](parameters) -> return_type {
    // 関数本体
};

ただし、戻り値型が明確な場合は-> return_typeを省略でき、コンパイラが自動推論します。

キャプチャ方式

ラムダ式は外側のスコープにある変数を「キャプチャ」して利用できます。主なキャプチャ方法は以下の通りです:

  • [=]:値によるキャプチャ(読み取り専用)
  • [&]:参照によるキャプチャ(読み書き可能)
  • [var, &other]:個別指定による混合キャプチャ

実用例:重複のない最長部分列の長さを求める

#include <bits/stdc++.h>
using namespace std;

void solve() {
    const int n = 10;
    int arr[] = {1, 2, 3, 4, 5, 6, 7, 7, 8, 9};

    auto has_duplicate = [&](int left, int right) {
        unordered_set<int> seen;
        for (int i = left; i <= right; ++i) {
            if (seen.count(arr[i])) return true;
            seen.insert(arr[i]);
        }
        return false;
    };

    auto find_max_length = [&]() {
        int max_len = 0;
        for (int i = 0, j = 0; i < n; ++i) {
            while (has_duplicate(j, i)) {
                ++j;
            }
            max_len = max(max_len, i - j + 1);
        }
        return max_len;
    };

    cout << find_max_length() << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    solve();
    return 0;
}

再帰的なラムダの実現

ラムダ式は匿名であるため、自分自身を呼び出すにはstd::functionを使用して型を明示的に宣言する必要があります。

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

void recursive_example() {
    function<void(int)> print_descending = [&](int x) {
        if (x <= 0) return;
        cout << x << '\n';
        print_descending(x - 1);
        cout << x << '\n';
    };
    print_descending(3);
}

注意点

値キャプチャ([=])では、キャプチャされたオブジェクトは暗黙的にconst扱いとなるため、非constメンバ関数を呼び出せません。例えば、mapoperator[]は非constなので、値キャプチャされたmapでは使用できません。このような場合は、参照キャプチャ([&])または引数として渡すことを推奨します。

タグ: C++ lambda STL

5月11日 08:33 投稿