五、Lambda表达式

Lambda表达式详解 mbda表达式详解,有详细的例子,简单易懂,一看就会,适合还没有接触过Lambda表达式的初学者学习 立即下载

Lambda表达式是一种用于定义匿名函数对象的便捷语法,自C++11引入后极大简化了代码编写,尤其是在需要传递短小函数逻辑的场景(如STL算法、回调函数等)

基本语法

[捕获列表] (参数列表) -> 返回类型 
{ 
    函数体 
}

//eg
aotu add = [](int a, int b) -> int 
{
	return a + b;
}

cout << add(3, 4) << endl;

捕获列表(Capture List)

定义了Lambda表达式可以访问的外部变量及其访问方式(值捕获或引用捕获)

  • []:不捕获任何外部变量
  • [x]:按值捕获变量x
  • [&x]:按引用捕获变量x
  • [=]:按值捕获所有外部作用域的变量
  • [&]:按引用捕获所有外部作用域的变量
  • [=, &x]:按值捕获所有外部变量,但是按引用捕获变量x
  • [&, x]:按引用捕获所有外部变量,但是按值捕获变量x
  • [this]:捕获Lambda表达式所在的成员函数所属对象的指针

参数列表(parameters)

与普通函数的参数列表相同

可以为空

返回类型(return_type)

在大多数情况下,返回类型可以被省略,编译器会根据函数体中的返回语句自动推断返回类型

函数体(function body)

包含了Lambda函数的实现;
除了可以使用参数之外,还可以使用捕获变量

#include <iostream>

using namespace std;

int main(int argc, const char *argv[])
{
    //不捕获任何外部变量[]
    auto printHello = []()
    {
        cout << "[]--->" << "hello world" << endl;
    };
    printHello();//"hello world"

    //按值捕获[x]
    int x = 10;
    auto add = [x](int a)
    {
        return a + x;
    };
    cout << "[x]-->" << add(5) << endl;//15

    //按引用捕获[&x]
    x = 10;
    auto setX = [&x]()
    {
        x = 20;
    };
    setX();
    cout << "[&x]-->" << x << endl;//20
  
    //按值捕获所有外部变量[=]
    x = 10;
    int y = 20;
    auto sum = [=]()
    {
        return x + y;
    };
    cout << "[=]-->" << sum() << endl;//30

    //按引用捕获所有外部变量[&]
    x = 10;
    y = 20;
    auto setXY = [&]()
    {
        x = 100;
        y = 200;
    };
    setXY();
    cout << "[&]-->" << x << " " << y << endl;//100 200

    //按值捕获所有外部变量,但按引用捕获特定的变量[=, &x]
    x = 10;
    y = 20;
    auto setXAndSum = [=, &x]()
    {
        x *= 2;
        return x + y;
    };
    cout << "[=, &x]-->" << setXAndSum() << " " << "x = " << x << endl;//40 20

    //按引用捕获所有外部变量,但按值捕获特定的变量[&, x]
    x = 10;
    y = 20;
    auto setYAndSum = [&, x]()
    {
        y *= 2;
        return x + y;
    };
    cout << "[&, x]-->" << setYAndSum() << " " << "y = " << y << endl;//50 40

    return 0;
}

注意事项

  1. 如果使用值捕获,lambda表达式的一个特性:捕获的变量默认为常量,或者说lambda是一个常量函数

    需要在函数体中修改变量值,需要加上说明符mutable,还多了一对()
    语法规定lambda表达式如果存在说明符,那么形参列表不能省略

    mutable说明符是为了突破const的限制而设置的

    被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中

    #include <iostream>
    
    using namespace std;
    
    int main(int argc, const char *argv[])
    {
        //按值捕获[x]
        int x = 10;
        auto add = [x] (int a) mutable
        {
            x = 100;
            return a + x;
        };
        cout << "[x]-->" << add(5) << endl;//105
    
        return 0;
    }
    
    
  2. Lambda表达式默认是const的,即它们不能修改捕获的变量的值,除非你明确指定捕获的变量为非const

  3. 使用Lambda表达式时,应注意其生命周期,特别是当按引用捕获外部变量时,必须确保被引用的变量在Lambda被调用时仍然有效

    避免捕获局部变量的引用后超出其作用域(悬垂引用)

    按值捕获的变量在Lambda创建时拷贝,后续外部变量修改不影响Lambda内的副本

  4. 性能优化:Lambda通常被编译器内联,性能接近手写代码;

    避免在频繁调用的路径中捕获大型对象(按值捕获可能带来拷贝开销)

  5. 与std::function关系

    Lambda可隐式转换为 std::function,但可能引入类型擦除开销

    直接使用auto存储lambda可保留类型信息,效率更高

底层实现

  1. Lambda表达式是通过生成一个匿名类(或称为闭包类型)的实例来实现的
  2. 这个匿名类内部重载了函数调用操作符operator() ,使得这个类的实例可以像函数一样被调用
  3. 每当定义一个Lambda表达式时,编译器会根据Lambda表达式的定义自动生成这样一个匿名类,并实例化一个该匿名类的对象

这个过程完全在编译时完成,不会导致运行时开销

// Lambda表达式
auto lambda = [x](int a) { return x + a; };

// 编译器生成的等效类
class __AnonymousLambda {
private:
    int x; // 按值捕获的变量
public:
    __AnonymousLambda(int x) : x(x) {}
    int operator()(int a) const { 
        return x + a; 
    }
};

//编译器将lambda变量实例化为这个匿名类的对象
__AnonymousLambda lambda(x);

常用用法

与STL算法结合

std::vector<int> nums = {1, 2, 3, 4};
// 使用Lambda过滤偶数
auto it = std::remove_if(nums.begin(), nums.end(), 
    [](int n) { return n % 2 != 0; });
nums.erase(it, nums.end());

作为回调函数

//函数
//callback = [](int result)
void processDate(std::function<void(int)> callback)
{
	cout << "processDate" << endl;
	callback(42);//调用lambda的函数体
}

//调用processDate函数,传入Lambda表达式
processDate([](int result)
{
	cout << "Result" << result;
}

Lambda高级特性

可变lambda(mutable关键字)

默认Lambda的 operator() 是 const 的,使用 mutable 允许修改按值捕获的变量:

int counter = 0;
auto increment = [counter]() mutable {
    counter++;
    std::cout << counter; 
};
increment(); // 输出 1
increment(); // 输出 2(修改的是副本)

捕获表达式(C++14)

std::unique_ptr<int> ptr = std::make_unique<int>(42);
auto lambda = [p = std::move(ptr)]() { 
    std::cout << *p; // p 是移动后的 unique_ptr
};

模板lambda(C++20)

auto print = []<typename T>(T value) {
    std::cout << value;
};
print(10);       // T 推导为 int
print(3.14);     // T 推导为 double
别再到处找了!GWAS数据下载保姆级指南:从IEU、FinnGen到UK Biobank一站搞定 本文提供GWAS数据下载的全面指南,涵盖IEU OpenGWAS、FinnGen、UK Biobank等五大核心数据库的获取策略。从数据库选型到实战操作,详细解析数据搜索、下载、预处理全流程,帮助科研人员高效获取GWAS数据,特别适合初学者快速上手。 阅读详情

相关推荐

【数字图像处理第四版课后习题答案】第2章 数字图像基础(含英文原版)

如图 P2.3 所示,视网膜图像中与点相对应的直径 x 是由类似的三角形得到的。即得出 x = 0.085d。根据第 2.1 节中的讨论,并结合一些自由解释,我们可以将眼窝视为一个方形传感器阵列,拥有大约 337,000 个元素,这相当于一个大约 580×580 个元素的阵列。假设元素间距相等,则在 1.5 毫米长的直线上有 580 个元素和 579 个空间,共计 1,159 个。换句话说,如果一个点的直径 d<1.3×10-6 m,或者 d<15.3×10 m,眼睛就无法检测到这个点。

weixin_56463218的博客 1万+

第5关:Lambda 表达式

这里的diff(sin)(x)分别传入了匿名函数sin和x,所以这里的f()其实是匿名函数sin()。所以这题还考察了回调函数。这里相关知识并没有说明,框架也给的莫名其妙,所以我一开始也没有看明白。本关要求学习者直接填入代码,然后运行程序并根据程序输出的结果判断填入的代码是否正确。这道题很多初学者应该看不太懂,因为这里对lambda匿名函数还有一个用处没有说明。本关的编程任务是补全 src/step5/step5.py 文件中的代码,完成函数。的值取 0.001 ,存放于变量。

m0_74775801的博客 1380

SpyGlass Lint脚本实战:如何用TCL自动化RTL代码检查(附完整配置模板)

本文详细介绍了如何利用TCL脚本实现SpyGlass Lint工具的自动化RTL代码检查。通过构建模块化、工程化的脚本框架,文章提供了从环境搭建、核心配置、规则定制到豁免管理的完整实战指南,并附有可复用的配置模板,旨在帮助IC设计工程师构建高效、一致的代码质量检查流水线。

weixin_29204205的博客 134

第五章:Lambda编程

Lambda表达式和成员引用 Lambda本质上是可以传递给其他函数的一小段代码 ; 函数式编程提供了另外一种解决问题的方法:把函数当作值 来对待; Lambda和集合 maxBy{} 指定比较哪个值找到最大元素,需要一个参数:一个函数 可以使用**it(默认参数名称)**来指定集合中的元素,如果当前上下文期望的是只有一个参数的lambda且这个参数的类型是可以被推断出来的; 成员引用 :: ...

Chrissen's Blog 897

告别手动标注!PDMS NakiToolkit插件安装与初体验:以Pipeline工具为例

本文详细介绍了PDMS NakiToolkit插件的安装与使用,特别是其Pipeline工具如何通过自动化标注和材料统计功能大幅提升三维工厂设计效率。从环境准备到实战演示,帮助工程师告别繁琐的手动标注工作,实现项目交付周期的大幅缩短。

weixin_30047059的博客 349

SAE J1939协议详解

SAE J1939协议是由美国汽车工程师协会(SAE)制定的主要针对商用车的CAN总线通讯协议,其基础是CAN2.0B协议,面向对象为客车和载重货车;船舶、农业机械等非路面设备。1.SAE J1939协议文档结构如下图:2.CAN的发展概况20世纪80年代,Bosch的工程人员开始研究用于汽车的串行总线系统,1986年, Bosch在SAE(汽车工程师协会)大会上提出了 CAN,1987年,INTEL就推出了第一片CAN控制芯片—82526;随后Philips半导体推出了82C200。

weixin_46184756的博客 8443

Python学习 Task05:函数与lambda表达式

函数的定义: 函数以def关键词开头,后接函数名和圆括号()。 函数执行的代码以冒号起始,并且缩进。 return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回None。 >>> def first (): print ('hello') print('world') >>> first () hello wor...

weixin_45774616的博客 444

使用Python开发TreeATE的测试脚本常见问题

ImportError: No module named py_compile 找不到 DevLangPython3.dll 以上2个问题都是没有安装正确的Python,当前TreeATE依赖32位Python 2.7版本,暂时不支持Python 3以上版本

蓝白云的专栏 1032

第五章 python 函数和 lambda 表达式

python 函数和 lambda 表达式一、函数1. 定义函数2. 调用函数3. 为函数提供文档4. 多个返回值5. 递归函数二、函数的参数1. 关键字(keyword)参数2. 参数默认值3. 参数收集(个数可变的参数)4. 逆向参数收集5. 函数的参数传递机制6. 变量作用域(1)访问被遮蔽的全局变量(2)在函数中申明全局变量三、 局部函数 一、函数 1. 定义函数 语法格式: def 函数...

w469001293的博客 771

Zynq裸机调试RTL8211FS网卡踩坑记:从ping不通到完美兼容的完整代码修改

本文详细记录了在Zynq平台上使用Xilinx SDK(XSDK)调试RTL8211FS网卡的完整过程,从最初的ping不通问题到最终实现完美兼容的解决方案。通过分析PHY芯片的寄存器配置差异,提供了关键代码修改和调试技巧,帮助开发者快速解决类似问题。

weixin_42550597的博客 418

保姆级教程:用高云GW2A开发板搭建RISC-V软核处理器(含DDR3内存优化配置)

本文提供了一份详细的保姆级教程,指导开发者使用高云GW2A-LV18PG256C8 FPGA开发板搭建RISC-V软核处理器系统。教程涵盖了从开发环境搭建、PicoRV32软核集成,到关键的DDR3内存控制器配置与优化,并深入讲解了时序约束与系统调试方法,帮助初学者和爱好者实现从逻辑设计到软硬件协同的深度实践。

2a4s6d8f0g的博客 563

Python练习task5:函数与 Lambda 表达式

函数 基本上所有的高级语言都支持函数,Python也不例外。Python不但能非常灵活地定义函数,而且本身内置了很多有用的函数,可以直接调用。 调用函数 Python内置了很多有用的函数,我们可以直接调用。 要调用一个函数,需要知道函数的名称和参数,比如求绝对值的函数abs,只有一个参数。也可以在交互式命令行通过help(abs)查看abs函数的帮助信息。调用函数的时候,如果传入的参数数量不对,会...

zyc_001117的博客 784

vue支付项目-APP支付宝支付功能

如果用户已安装支付宝客户端,商家 App 唤起支付宝完成支付,支付完后跳回到商家 App 内,最后展示支付结果。如果用户没有安装支付宝客户端,商家 App 内会调起支付宝网页支付收银台,用户登录支付宝账号,支付完后展示支付结果。1.点击按钮开通或者续费,会验证是否选择会员商品以及对协议是否查看选中(这里根据项目需要自行验证,可忽略),验证通过打开选择支付方式弹窗页面,选择微信支付或者支付宝支付;4.可取消支付,放弃支付会返回会员页面,页面提示支付取消;1.判断支付方式,如果是2,则是支付宝支付方式。

总结前端开发中遇到的问题,分享前端知识 1万+

五、lambda表达式

(一)lambda表达式的使用 lambda x,y:2*x+y #冒号前面放参数,多个参数用逗号隔开,冒号后面加执行操作,返回一个函数对象 f=lambda x,y:2*x+y #定义f为功能函数 print(f(3,4)) 输出10 (二)lambda表达式的应用 (1)、 #过滤器filter(第一个参数为一个函数或者None,第二个参数为一个可迭代对象,eg:List,返回包...

weixin_41039168的博客 1522

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

lambda表达式的解析(五) Lambda表达式与闭包类型

在讲述如何解析转换成员访问表达式之前,先来讲一些预备知识。 一个标准的lambda表达式应该是  ( 参数列表 ) => 表达式或表达式块 其中参数列表和方法的参数列表类似,不过lambda表达式更灵活,允许用的时候不用显示声明参数的类型甚至在一个参数的时候括号也可以不用

guoyichao的专栏 2774

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Java基础之lambda表达式(五)

本篇目的:Java基础之lambda表达式Java 8 引入了一个新的特性:Lambda 表达式。Lambda 表达式是一种用于简化代码编写和表达式执行的语法糖。它可以使代码更简洁、更易读,并且可以更好地利用现代多核处理器的计算能力。Lambda 表达式允许我们将一个函数作为一个对象的参数传递。它通常用于实现简短、无状态的函数。Lambda 表达式可以用于实现接口中的抽象方法,从而使代码更加简洁。Lambda 表达式由一对花括号 {} 包围,其中包含一个或多个参数,以及一个箭头 ->。

Android系统攻城狮 1394

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

java lambda表达式_java知识总结(五):lambda表达式

lambda表达式是jdk8中新增的特性,用于取代大部分的匿名内部类,使代码更加简洁。jdk8之前常使用匿名类: new Thread(new Runnable() { @Override public void run() { System.out.println("线程:"+Thread.currentThread().getName()); } });jdk8新增的lambda表达式: //...

weixin_39611754的博客 212

Android开发技巧 (五) —— Lambda表达式

Lambda表达式本质是一种匿名方法,它既没有方法名,也没有访问修饰符和返回值类型,用它来写代码更简洁,更易懂。 Lambda是Java8的新特性,所以要在app/build.gardle中添加: android { ...... compileOptions{ sourceCompatibility JavaVersion.VERSION_1_8 targ...

干燥的空气,湿润的呼吸 798

Lambda表达式例五

Lambda

Leon_Jinhai_Sun的博客 174

java中如何使用Lambda表达式(五)

这是因为Lambda表达式可以转换为函数式接口的实例,而函数式接口可以作为方法参数来接收Lambda表达式。函数式接口是一个只有一个抽象方法的接口,Lambda表达式可以被赋值给这个抽象方法,从而实现函数作为返回值的功能。通过这种方式,我们可以将行为抽象出来,灵活地传递不同的函数实现,从而实现更加灵活和通用的代码设计。通过Lambda表达式实现函数作为返回值,我们可以更简洁地定义一些函数式接口的实现,使代码更为简洁和易读。方法,接受一个int类型的参数并返回一个int类型的结果。函数式接口的实现,而。

不安分的猿人的专栏 463

Java语法基础五: Lambda表达式与函数式接口

Lambda表达式和函数式接口的定义、作用、关系和具体示例

Xyuan的博客 794

C++学习笔记(五)Lambda 表达式

lambda表达式定义了一个匿名函数,并且可以捕获所定义的匿名函数外的变量。它的语法形式是: [ capture ] ( parameter ) option -> return_type { body; }; 其中: capture 捕获列表 parameter 参数列表 option 函数选项 return_type 函数返回值类型 body 函数体 比如 // definati...

YK_LaNce的博客 352

windows C++-Lambda表达式(五)

你可以显式或隐式捕获 this 指针,以提供对封闭类的函数和数据成员的访问路径。Visual Studio 2017 版本 15.3 或更新版本(/std:c++17 及更新版本可用):在原始对象超出范围后,当可能会执行代码的异步或并行操作将使用 lambda 时,按值捕获 this ([*this])。但是,你可以将具有托管类型的实际参数传递到 lambda 表达式的形式参数列表。ApplyScale 函数使用 lambda 表达式打印小数位数值与 vector 对象中的每个元素的乘积。

王马的博客 756

java lambda 表达式适合哪些地方_java知识总结(五):lambda表达式

lambda表达式是jdk8中新增的特性,用于取代大部分的匿名内部类,使代码更加简洁。jdk8之前常使用匿名类: new Thread(new Runnable() { @Override public void run() { System.out.println("线程:"+Thread.currentThread().getName()); } });jdk8新增的lambda表达式: //...

weixin_29131533的博客 277

lambda表达式Stream流学习五、六 —Lambda的方法引用以及Stream流介绍

Lambda的方法引用以及Stream流介绍

头好重好重的博客 347

C++11(五)Lambda表达式+包装器

如果想要对一个数据集合中的元素进行排序,可以使用std::sort方法。 如果待排序元素为自定义类型,需要用户定义排序时的比较规则: 随着C++语法的发展,人们开始觉得上面的写法太复杂了,每次为了实现一个algorithm算法,都要重新去写一个类,如果每次比较的逻辑不一样,还要去实现多个类,特别是相同类的命名,这些都给编程者带来了极大的不便。因此,在C++11语法中出现了Lambda表达式。 上述代码就是使用C++11中的lambda表达式来解决Lambda表达式也可以叫做匿名函数 书写格式:注意:在lam

想要上进的coder的博客 469
上一篇: 四、C++ - 泛型编程
木子21
博客等级 码龄9年 58粉丝 12原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值