「学习笔记」Lambda 表达式
Lambda 表达式因数学中的 \(\lambda\) 演算得名, 直接对应于其中的 lambda 抽象. Lambda 表达式能够捕获作用域中的变量的无名函数对象, 我们可以将其理解为一个匿名的内联函数, 可以用来替换独立函数或者函数对象, 从而使代码更可读. 但是从本质上来讲, Lambda 表达式只是一种语法糖, 因为它能完成的工作也可以用其他复杂的 C++ 语法来实现.
下面是 Lambda 表达式的语法结构.
[capture] (parameters) mutable -> return-type {statement}
capture
: 捕获;
parameters
: 参数;
mutable
: 可变规范;
return-type
: 返回类型;
statement
: Lambda 表达式的主体;
下面是更高版本的 C++ 的有关 Lambda 表达式的语法. [1]
[capture] (parameters) lambda说明符 约束(可选) {statement}
[capture] {statement} // (C++23 前)
[capture] lambda说明符 {statement} // (C++23 起)
[capture] < 模板形参 > 约束(可选) // (C++20 起)
(parameters) lambda说明符 约束(可选) {statement} // (C++20 起)
[capture] < 模板形参 > 约束(可选) {statement} // (C++20 起 C++23 前)
[capture] < 模板形参 > 约束(可选) lambda说明符 {statement} //(C++23 起)
capture 捕获
捕获 是一个含有零或更多个捕获符的逗号分隔列表, 可以 默认捕获符 开始. 默认捕获符只有
&
(以引用隐式捕获被使用的自动变量)和=
(以复制隐式捕获被使用的自动变量).
当出现任一默认捕获符时, 都能隐式捕获当前对象(*this). 如果隐式捕获它, 那么会始终以引用捕获,即使默认捕获符是 =
. 当默认捕获符为 =
时, *this 的隐式捕获被弃用. (C++20 起)
当默认捕获符是 &
时, 后继的简单捕获符不能以 &
开始.
struct S2 { void f(int i); };
void S2::f(int i)
{
[&]{}; // OK:默认以引用捕获
[&, i]{}; // OK:以引用捕获,但 i 以值捕获
[&, &i] {}; // 错误:以引用捕获为默认时的以引用捕获
[&, this] {}; // OK:等价于 [&]
[&, this, i]{}; // OK:等价于 [&, i]
}
当默认捕获符是 =
时, 后继的简单捕获符必须以 &
开始, 或者为 *this (C++17 起) 或 this (C++20 起).
struct S2 { void f(int i); };
void S2::f(int i)
{
[=]{}; // OK:默认以复制捕获
[=, &i]{}; // OK:以复制捕获,但 i 以引用捕获
[=, *this]{}; // C++17 前:错误:无效语法
// C++17 起:OK:以复制捕获外围的 S2
[=, this] {}; // C++20 前:错误:= 为默认时的 this
// C++20 起:OK:同 [=]
}
任何捕获符只可以出现一次, 并且名字不能与形参相同:
struct S2 { void f(int i); };
void S2::f(int i)
{
[i, i] {}; // 错误:i 重复
[this, *this] {}; // 错误:"this" 重复(C++17)
[i] (int i) {}; // 错误:形参和捕获的名字相同
}
parameters 参数
大多数情况下类似于函数的参数列表.
C++14 中, 若参数类型是泛型, 则可以使用 auto
声明类型:
int x[] = {5, 1, 7, 6, 1, 4, 2};
std::sort(x, x + 7, [](int a, int b) { return (a > b); });
for (auto i : x) std::cout << i << " ";
这份代码将打印出 x
数组从大到小排序后的结果.
mutable 可变规范
利用可变规范, Lambda 表达式的主体可以修改通过值捕获的变量. 若使用此关键字, 则 parameters 不可省略 (即使为空).
一个例子, 使用 capture 捕获字句 中的例子, 来观察 \(a\) 的值的变化:
int a = 0;
auto func = [a]() mutable { ++a; };
此时 lambda 中的 \(a\) 的值改变为 \(1\), lambda 外的 \(a\) 保持不变.
return-type 返回类型
用于指定 Lambda 表达式的返回类型. 若没有指定返回类型, 则返回类型将被自动推断 (行为与用 auto
声明返回值的普通函数一致). 具体的, 如果函数体中没有 return
语句, 返回类型将被推导为 void
, 否则根据返回值推导. 若有多个 return
语句且返回值类型不同, 将产生编译错误.
statement Lambda 主体
Lambda 主体可包含任何函数可包含的部分。普通函数和 Lambda 表达式主体均可访问以下变量类型:
- 从封闭范围捕获变量
- 参数
- 本地声明的变量
- 在一个
class
中声明时,若捕获this
,则可以访问该对象的成员 - 具有静态存储时间的任何变量,如全局变量
大部份资料来自 \(\texttt{OI-Wiki}\).
「学习笔记」Lambda 表达式的更多相关文章
- 「学习笔记」FFT 快速傅里叶变换
目录 「学习笔记」FFT 快速傅里叶变换 啥是 FFT 呀?它可以干什么? 必备芝士 点值表示 复数 傅立叶正变换 傅里叶逆变换 FFT 的代码实现 还会有的 NTT 和三模数 NTT... 「学习笔 ...
- 「学习笔记」Min25筛
「学习笔记」Min25筛 前言 周指导今天模拟赛五分钟秒第一题,十分钟说第二题是 \(\text{Min25}\) 筛板子题,要不是第三题出题人数据范围给错了,周指导十五分钟就 \(\text{AK ...
- 「学习笔记」FFT 之优化——NTT
目录 「学习笔记」FFT 之优化--NTT 前言 引入 快速数论变换--NTT 一些引申问题及解决方法 三模数 NTT 拆系数 FFT (MTT) 「学习笔记」FFT 之优化--NTT 前言 \(NT ...
- 「学习笔记」Treap
「学习笔记」Treap 前言 什么是 Treap ? 二叉搜索树 (Binary Search Tree/Binary Sort Tree/BST) 基础定义 查找元素 插入元素 删除元素 查找后继 ...
- 「学习笔记」字符串基础:Hash,KMP与Trie
「学习笔记」字符串基础:Hash,KMP与Trie 点击查看目录 目录 「学习笔记」字符串基础:Hash,KMP与Trie Hash 算法 代码 KMP 算法 前置知识:\(\text{Border} ...
- 「学习笔记」平衡树基础:Splay 和 Treap
「学习笔记」平衡树基础:Splay 和 Treap 点击查看目录 目录 「学习笔记」平衡树基础:Splay 和 Treap 知识点 平衡树概述 Splay 旋转操作 Splay 操作 插入 \(x\) ...
- 「C++11」Lambda 表达式
维基百科上面对于 lambda 的引入是如下描述的: 在标准 C++,特别是当使用 C++ 标准程序库算法函数诸如 sort 和 find.用户经常希望能够在算法函数调用的附近定义一个临时的述部函数( ...
- 0028 Java学习笔记-面向对象-Lambda表达式
匿名内部类与Lambda表达式示例 下面代码来源于:0027 Java学习笔记-面向对象-(非静态.静态.局部.匿名)内部类 package testpack; public class Test1{ ...
- 「学习笔记」wqs二分/dp凸优化
[学习笔记]wqs二分/DP凸优化 从一个经典问题谈起: 有一个长度为 \(n\) 的序列 \(a\),要求找出恰好 \(k\) 个不相交的连续子序列,使得这 \(k\) 个序列的和最大 \(1 \l ...
- 高放的c++学习笔记之lambda表达式
lambda表达式:可以让代码看起来更整洁,有些结构简单且用的次数少的函数可以用lambda表达式替代, 通常结构是这样的[捕获列表](参数列表){函数部分} 捕获列表: lambda表达式如果在一个 ...
随机推荐
- python:模拟购票的小程序
问题描述:小白学习python的第N天,继续练习.做一个模拟购票的小程序,没有用数据库和文件来存储数据,只是能够单词选择. # hzh 每天进步一点点 # 2022/5/13 17:24 import ...
- redis 基于 漏斗算法 实现对 api 的限流
漏斗算法 漏桶算法的原理: 漏桶有一定的容量,给漏桶注水,当单位时间内注入水量大于流出水量,漏桶内积累的水就会越来越多,直到溢出. 就好比大批量请求访问nginx相当于注水,nginx根据配置按照固定 ...
- Semantic Kernel 入门系列:🥑Memory内存
了解的运作原理之后,就可以开始使用Semantic Kernel来制作应用了. Semantic Kernel将embedding的功能封装到了Memory中,用来存储上下文信息,就好像电脑的内存一样 ...
- linux网络开发者定位问题常用工具和命令总结
本文章来自我的微信个人技术公众号---网络技术修炼,公众号中总结普及网络基础知识,包括基础原理.网络方案.开发经验和问题定位案例等,欢迎关注. Linux网络开发者面临的问题往往比较复杂,因此需要使用 ...
- 【ACM组合数学 | 错排公式】写信
题目链接:https://ac.nowcoder.com/acm/contest/54484/B 题意很简单,但是数据范围偏大. 错排公式 首先来推导一下错排公式: \[D(n) = n!\sum_{ ...
- Spring中事务嵌套这么用一定得注意了!!
前言 最近项目上有一个使用事务相对复杂的业务场景报错了.在绝大多数情况下,都是风平浪静,没有问题.其实内在暗流涌动,在有些异常情况下就会报错,这种偶然性的问题很有可能就会在暴露到生产上造成事故,那究竟 ...
- 封装统一请求状态返回Result
1.测试数据 public class Test { public static void main(String[] args){ System.out.println("Response ...
- SpringCloud导入spring boot项目当作子模块微服务IDEA不识别子module问题
1.在父工程下面引入module. <modules> <module>study-design-mode</module> </modules> 2. ...
- 笔记八:linux系统编程之IO
笔记:linux系统编程之IO 应用层 内核层 硬件层 应用层:数据结构 .java.android.C.C++,C#: l inux高级编程:涉及内核为应用层提供接口函数: 内核五大 ...
- 新概念英语(New Concept English),前言
本书向读者提供了一套完整的,经过实践检验的英语学习体系,使得学生能够发挥自己的最大潜能. 听力 口语 阅读 写作 学习语言不在于掌握一套规则和积累大量词汇. 而在于如何运用所学的知识. 学习单词,必须 ...