首页 > 其他分享 >「学习笔记」Lambda 表达式

「学习笔记」Lambda 表达式

时间:2023-07-10 14:22:05浏览次数:44  
标签:capture int 捕获 C++ 笔记 表达式 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 语句且返回值类型不同, 将产生编译错误.

auto lam = [](int a, int b) -> int

statement Lambda 主体

Lambda 主体可包含任何函数可包含的部分。普通函数和 Lambda 表达式主体均可访问以下变量类型:

  • 从封闭范围捕获变量
  • 参数
  • 本地声明的变量
  • 在一个 class 中声明时,若捕获 this,则可以访问该对象的成员
  • 具有静态存储时间的任何变量,如全局变量

大部分资料来自 \(\texttt{OI-Wiki}\).


  1. 该资料来自Lambda表达式(C++11起)-cppreference.com ↩︎

标签:capture,int,捕获,C++,笔记,表达式,Lambda
From: https://www.cnblogs.com/yifan0305/p/17539890.html

相关文章

  • 学习笔记407—读者们的福音,Z-Library又双叒回归了!
    读者们的福音,Z-Library又双叒回归了!而且还支持桌面客户端。1、官网链接:https://zh.go-to-zlibrary.se/#useful_link_tab2、网页入口:https://singlelogin.se/ 意在交流学习,欢迎点赞评论......
  • 莫队学习笔记
    这是一篇模仿算导的学习笔记/题解。例题:P1494给定一个长为\(n\)的数组\(a\)和\(m\)个询问(有序数对)\(b_i=(l_i,r_i)\),询问允许离线,对每个询问\((l,r)\)求出满足\(l\lei\ltj\ltr\wedgea_i=a_j\)的数对\((i,j)\)数量.证明:若数\(x\)在\(a\)数组下标为......
  • EL表达式 (详解) .
    EL表达式   1、EL简介1)语法结构    ${expression}2)[]与.运算符   EL提供.和[]两种运算符来存取数据。   当要存取的属性名称中包含一些特殊字符,如.或?等并非字母或数字的符号,就一定要使用[]。例如:     ${user.My-Name}应当改......
  • .NET写一个自己的Lambda表达式与表达式树
    LambdaExpression继承ExpressionExpression又继承LambdaExpressio所以,Expression与Expression的区别在于:泛型类以静态类型的方法标识了它是什么种类的表达式,也就是说,他确定了返回类型和参数。所以显然,TDelegate必须是一个委托类型。注意:并非所有的Lambda表达式都能转......
  • 线段树学习笔记与总结
    线段树学习笔记与总结目录线段树引入资源链接模板线段树引入我们经常会遇到需要维护一个序列的问题,例如给定一个整数序列,每次操作会修改序列某个位置上的数,或是海间你序列巾某个区问内所有数的和,用“暴力"算法,单点修改的复杂度为\(O(1)\),询问区间和的单次复杂度为\(O(N)\)......
  • abc065d <贪心+最小生成树> [lambda表达式]
    D-Built?//https://atcoder.jp/contests/abc065/tasks/arc076_b//贪心+最小生成树//关键在于意识到,连接x或y相邻的边代价最小,因而无需考虑全部的边,仅需考虑这些相邻边即可(贪心)//学习://1.lambda写法https://www.cnblogs.com/yaya12138/p/11815475.html//......
  • python笔记:第五章条件循环语句
    1.print和import1.1打印多个参数同时打印多个表达式,用逗号分隔print('age:',42)>age:13#注意两个表达式之间有空格不加空格的输出方式print('block'+'chain')>blockchain自定义分隔符print('L','M','C',sep='-')>L......
  • 并查集学习笔记
    什么是并查集顾名思义,并查集有两个最主要的作用:合并集合和查询某两个元素是不是在同一个集合内。或者说:并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个......
  • Hash 学习笔记与总结
    Hash算法学习笔记与总结目录Hash字符串Hash信息学奥赛一本通AcWing模板模板题题目大意CODEHash表拉链法开放寻址法模板题题目大意CODEHash哈希算法是通过一个哈希函数H,将一种数据(包活字符串、较大的数等)转化为能够用变量表示或是直接就可作为数组下标的数,道过哈希函数......
  • 高等数学笔记
    第一章函数与极限第一节映射与函数映射函数......