写在前面
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 最强应用!