C++lambda一些有用的操作总结

 
Category: C++

写在前面

lambda 简介

这里我最喜欢的一个功能就是参数捕获列表, 可以很大程度上减少参数的重复传递, 一个 & 足矣(当然也不能滥用)

参数捕获

常见操作

指定比较规则(sort, priority_queue)

指定其他规则

简短函数的封装

递归支持

用递归版本的 lambda 主要是方便参数的捕获.

试想回溯法中参数一多了, 写成独立的两个函数就要传入很多并不是递归变量的变量, 没有必要, 不过写递归lambda 的坏处就是不如两个函数那样简洁明了.

这里有两种比较常见的方法, 第一种就是每次刷题都用的function类模板(函数对象)

下面的例子是经典的反转链表递归写法(复习一下)

function<ListNode *(ListNode *)> r1 = [&](ListNode *node) {
    if (!node || !node->next)
        return node;
    auto ans = r1(node->next);
    node->next->next = node;
    node->next = nullptr;
    return ans;
};
cout << r1(l1); // l1 是链表头结点, 下同

或者用调用自己的方法(好处是不用写两遍函数签名, 坏处是每次第一参数都要写函数名)

auto r2 = [&](auto &&r2, ListNode *node) {
    if (!node || !node->next)
        return node;
    auto ans = r2(r2, node->next);
    node->next->next = node;
    node->next = nullptr;
    return ans;
};
cout << r2(r2, l1); // 

骚操作

初始化全局变量(在 main 之前执行的函数)

一个很好的例子就是力扣的素数相关的题目, 需要先初始化出来素数数组, 这时候用 lambda 就非常舒适了:

constexpr int MX = 1e6;
int primes[MX], cnt{};
bitset<MX + 2> pri; // record 

int _ = [] {
    for (int i{2}; i <= MX; ++i) {
        if (!pri[i])
            primes[cnt++] = i;
        for (int j{}; i * primes[j] <= MX; ++j) {
            pri[i * primes[j]] = 1;
            if (i % primes[j] == 0)
                break;
        }
    }
    return 0;
}();

我愿称之为 lambda 最强应用!

初始化