c++ Lambda函数学习

​C++ 中的 Lambda​ C++11引入了lambda表达式,使得C++程序员能够编写更简洁的回调函数和闭包,表达式用于定义并创建匿名的函数对象,以简化编程工作。 阅读详情

c++ Lambda函数学习

或许,Lambda 表达式算得上是 C++ 11 新增特性中最激动人心的一个。这个全新的特性听起来很深奥,但却是很多其他语言早已提供(比如 C#)或者即将提供(比如 Java)的。简而言之,Lambda 表达式就是用于创建匿名函数的。GCC 4.5.x 和 Microsoft Visual Studio 早已提供了对 lambda 表达式的支持。在 GCC 4.7 中,默认是不开启 C++ 11 特性的,需要添加 -std=c++11 编译参数。而 VS2010 则默认开启。

为什么说 lambda 表达式如此激动人心呢?举一个例子。标准 C++ 库中有一个常用算法的库,其中提供了很多算法函数,比如 sort() 和 find()。这些函数通常需要提供一个“谓词函数 predicate function”。所谓谓词函数,就是进行一个操作用的临时函数。比如 find() 需要一个谓词,用于查找元素满足的条件;能够满足谓词函数的元素才会被查找出来。这样的谓词函数,使用临时的匿名函数,既可以减少函数数量,又会让代码变得清晰易读。

下面来看一个例子:

#include <algorithm>
#include <cmath>

void abssort(float *x, unsigned N)
{
  std::sort(x,
            x + N,
            [](float a, float b) { return std::abs(a) < std::abs(b); });
}

从上面的例子来看,尽管支持 lambda 表达式,但 C++ 的语法看起来却很“神奇”。lambda 表达式使用一对方括号作为开始的标识,类似于声明一个函数,只不过这个函数没有名字,也就是一个匿名函数。这个匿名函数接受两个参数,a和b;其返回值是一个 bool 类型的值,注意,返回值是自动推断的,不需要显式声明,不过这是有条件的!条件就是,lambda 表达式的语句只有一个 return。函数的作用是比较 a、b 的绝对值的大小。然后,在此例中,这个 lambda 表达式作为一个闭包被传递给 std::sort() 函数。

下面,我们来详细解释下这个神奇的语法到底代表着什么。

我们从另外一个例子开始:

std::cout << [](float f) { return std::abs(f); } (-3.5);

输出值是什么?3.5!注意,这是一个函数对象(由 lambda 表达式生成),其实参是 -3.5,返回值是参数的绝对值。lambda 表达式的返回值类型是语言自动推断的,因为std::abs()的返回值就是 float。注意,前面我们也提到了,只有当 lambda 表达式中的语句“足够简单”,才能自动推断返回值类型。

C++ 11 的这种语法,其实就是匿名函数声明之后马上调用(否则的话,如果这个匿名函数既不调用,又不作为闭包传递给其它函数,那么这个匿名函数就没有什么用处)。如果你觉得奇怪,那么来看看 JavaScript 的这种写法:

function() {} ();
function(a) {} (-3.5);

C++ 11 的写法完全类似 JavaScript 的语法。

如果我不想让 lambda 表达式自动推断类型,或者是 lambda 表达式的内容很复杂,不能自动推断怎么办?比如,std::abs(float)的返回值是 float,我想把它强制转型为 int。那么,此时,我们就必须显式指定 lambda 表达式返回值的类型:

std::cout << [](float f) -> int { return std::abs(f); } (-3.5);

这个语句与前面的不同之处在于,lambda 表达式的返回时不是 float 而是 int。也就是说,上面语句的输出值是 3。返回值类型的概念同普通的函数返回值类型是完全一样的。

当我们想引用一个 lambda 表达式时,我们可以使用auto关键字,例如:

auto lambda = [] () -> int { return val * 100; };

auto关键字实际会将 lambda 表达式转换成一种类似于std::function的内部类型(但并不是std::function类型,虽然与std::function“兼容”)。所以,我们也可以这么写:

std::function<int()> lambda = [] () -> int { return val * 100; };

如果你对std::function这种写法感到很神奇,可以查看 C++ 11 的有关std::function的用法。简单来说,std::function就是一个可调用对象模板类,代表一个可调用对象,接受 0 个参数,返回值是int。所以,当我们需要一个接受一个double作为参数,返回int的对象时,就可以写作:std::function。

引入 lambda 表达式的前导符是一对方括号,称为 lambda 引入符(lambda-introducer)。lambda 引入符是有其自己的作用的,不仅仅是表明一个 lambda 表达式的开始那么简单。lambda 表达式可以使用与其相同范围 scope 内的变量。这个引入符的作用就是表明,其后的 lambda 表达式以何种方式使用(正式的术语是“捕获”)这些变量(这些变量能够在 lambda 表达式中被捕获,其实就是构成了一个闭包)。目前为止,我们看到的仅仅是一个空的方括号,其实,这个引入符是相当灵活的。例如:

float f0 = 1.0;
std::cout << [=](float f) { return f0 + std::abs(f); } (-3.5);

其输出值是 4.5。[=] 意味着,lambda 表达式以传值的形式捕获同范围内的变量。另外一个例子:

float f0 = 1.0;
std::cout << [&](float f) { return f0 += std::abs(f); } (-3.5);
std::cout << '\n' << f0 << '\n';

输出值是 4.5 和 4.5。[&] 表明,lambda 表达式以传引用的方式捕获外部变量。那么,下一个例子:

float f0 = 1.0;
std::cout << [=](float f) mutable { return f0 += std::abs(f); } (-3.5);
std::cout << '\n' << f0 << '\n';

这个例子很有趣。首先,[=]意味着,lambda 表达式以传值的形式捕获外部变量。C++ 11 标准说,如果以传值的形式捕获外部变量,那么,lambda 体不允许修改外部变量,对 f0 的任何修改都会引发编译错误。但是,注意,我们在 lambda 表达式前声明了mutable关键字,这就允许了 lambda 表达式体修改 f0 的值。因此,我们的例子本应报错,但是由于有 mutable 关键字,则不会报错。那么,你会觉得输出值是什么呢?答案是,4.5 和 1.0。为什么 f0 还是 1.0?因为我们是传值的,虽然在 lambda 表达式中对 f0 有了修改,但由于是传值的,外部的 f0 依然不会被修改。

上面的例子是,所有的变量要么传值,要么传引用。那么,是不是有混合机制呢?当然也有!比如下面的例子:

float f0 = 1.0f;
float f1 = 10.0f;
std::cout << [=, &f0](float a) { return f0 += f1 + std::abs(a); } (-3.5);
std::cout << '\n' << f0 << '\n';

这个例子的输出是 14.5 和 14.5。在这个例子中,f0 通过引用被捕获,而其它变量,比如 f1 则是通过值被捕获。

下面我们来总结下所有出现的 lambda 引入符:

[]        // 不捕获任何外部变量
[=]      // 以值的形式捕获所有外部变量
[&]      // 以引用形式捕获所有外部变量
[x, &y] // x 以传值形式捕获,y 以引用形式捕获
[=, &z]// z 以引用形式捕获,其余变量以传值形式捕获
[&, x]  // x 以值的形式捕获,其余变量以引用形式捕获

另外有一点需要注意。对于[=]或[&]的形式,lambda 表达式可以直接使用 this 指针。但是,对于[]的形式,如果要使用 this 指针,必须显式传入:

[this]() { this->someFunc(); }();

至此,我们已经大致了解了 C++ 11 提供的 lambda 表达式的概念。建议通过结合 lambda 表达式与std::sort()或std::for_each()这样的标准函数来尝试使用一下吧!

C 语言支持 Lambda 表达式吗?C 语言如何使用动态链接库?C 语言如何使用静态链接库? Lambda表达式是一种匿名函数,它可以作为参数传递给其他函数或者直接被调用。Lambda表达式通常用于简化代码、提高代码可读性和编写更简洁的代码。C语言不直接支持Lambda表达式,因为C语言是一种过程式编程语言,它没有内置的Lambda表达式语法。然而,可以使用函数指针来模拟Lambda表达式的功能。通过定义一个函数指针,并将其指向一个匿名函数或者已有函数,可以实现类似Lambda表达式的效果。 阅读详情

相关推荐

一文读懂C++中的Lambda函数:简洁、高效、灵活

一、匿名函数的基本语法; 二、捕获列表: 2.1、值捕获, 2.2、引用捕获, 2.3、隐式捕获, 2.4、空捕获列表, 2.5、表达式捕获, 2.6、泛型 Lambda, 2.7、可变lambda, 2.8、混合捕获, 2.10、Lambda捕获列表总结。 lambda表达式的目的是把函数写的更加内聚;只需要在内部使用,就没必要写到外部,干扰其他函数,同时使代码更简洁。 如果捕获列表为[&],则表示所有的外部变量都按引用传递给lambda使用。

Lion_Long的博客 1万+

C++11 的for_each、lambda表达式

C++STL的非变易算法(Non-mutating algorithms)是一组不破坏操作数据的模板函数,用来对序列数据进行逐个处理、元素查找、子序列搜索、统计和匹配。for_each用于逐个遍历容器元素,它对迭代器区间[first,last)所指的每一个元素,执行由单参数函数对象f所定义的操作。 原型: template<class InputIterator, class Function>

葫芦与瓢的博客 5259

小龙虾 OpenClaw 安装全攻略:本地部署 AI 智能体一步到位

OpenClaw(昵称小龙虾)是一款 MIT 开源协议的本地优先 AI 智能体执行网关,支持多平台接入、本地部署,能实现自然语言驱动的设备自动化操作,区别于纯对话 AI,可直接操控系统执行实际任务,数据全程本地存储更安全。本文带来 2026 最新版 OpenClaw 安装教程,适配 Windows/macOS/Linux 全系统,新手也能一键搞定。

lujiawei00的专栏 1976

C++ Lambda函数

c++ Lambda函数

一个码头 5565

Fast DDS源代码走读

DDS, PDP, EPD, DataWriter, DataReader

weixin_43082062的博客 713

Python-自动化绘制股票价格通道线

创建更强大、更可靠的价格通道检测算法。

探索人工智能领域 948

C++ :Lambda函数的浅学习

lambda表达式又被称之为lambda函数,是c++11的新特性,下面我们看一下lambda表达式的参数等说明:[函数对象参数](操作符重载函数参数)mutable或exception声明->返回值类型{函数体下面我们说明一下参数类型以及变量截取规则:1.[函数对象参数]:捕捉列表。捕捉列表总是出现在lambda函数的开始处,[]是lambda函数的引出符,这个必须存在不可以省略。编译器会根据引出符判断接下来的代码是否是Lambda函数。捕捉列表能够捕捉上下文中的变量以供Lambda函数使用。

Sxy_wspsby的博客 786

倍福EL6002做RS232通信获取称重数据..

本文介绍EL6002模块通过RS232自由口通信协议获取从站数据。具体数据对照说明手册即可。

weixin_41883890的博客 1012

[转]c++ Lambda函数学习

或许,Lambda 表达式算得上是 C++ 11 新增特性中最激动人心的一个。这个全新的特性听起来很深奥,但却是很多其他语言早已提供(比如 C#)或者即将提供(比如 Java)的。简而言之,Lambda 表达式就是用于创建匿名函数的。GCC 4.5.x 和 Microsoft Visual Studio 早已提供了对 lambda 表达式的支持。在 GCC 4.7 中,默认是不开启 C++ 11 ...

蓦然回首 389

设计四翼无人机(Quadcopter)的自主降落控制算法

为四翼无人机建立动力学模型,包括其姿态(Pitch, Roll, Yaw)和位置(X, Y, Z)的变化。可以使用Aerospace Blockset中的预制模块,或者根据具体需求构建自定义模型。示例:简化动力学模型利用块模拟四翼无人机的基本行为,确保模型能够反映电机输出如何影响姿态和位置变化。

amy_mhd的博客 242

Image Sensor卷帘曝光(Rolling Shutter)基本原理以及对曝光行的通俗理解

由于CMOS sensor的曝光方式是一行一行的方式进行的,任何一个pixel的曝光时间是一样的,也就是同一行上的每个pixel的曝光开始点和曝光的时间都是一模一样的,所以同一行的所有点所接受到的能量是一样的,而在不同行之间虽然曝光时间都是一样的,但是曝光的开始点是不同的,所以不同行之间所接受到的能量是不一定相同的。至此完成了这一行的曝光。还是以桶装水为比喻: 排成一行的桶(桶的数量和每个桶的大小确定),每一曝光行为单位的时间内每一个桶加水都是一样,需要多少个曝光行才能使的所有水桶加起来的水达到1L。

大熊 3929

C++:Lambda函数学习

C++:Lambda函数学习 或许,Lambda 表达式算得上是 C++ 11 新增特性中最激动人心的一个。这个全新的特性听起来很深奥,但却是很多其他语言早已提供(比如 C#)或者即将提供(比如 Java)的。简而言之,Lambda 表达式就是用于创建匿名函数的。GCC 4.5.x 和 Microsoft Visual Studio 早已提供了对 lambda 表达式的支持。在 GCC 4.7 中...

Mr.Andy的博客 305

【调优】OpenClaw从零开始高阶调优之skill篇

本文详细解析了OpenClaw技能系统的核心机制。首先介绍了技能的分层加载逻辑,按照优先级从高到低依次为:工作区专属技能、全局共享技能、出厂自带技能和自定义路径技能。通过流程图展示了从扫描到注册的完整加载流程,并解释了同名技能覆盖规则。随后深入剖析了SKILL.md文件结构,包含YAML元数据定义技能属性和Markdown正文说明使用方法,以公众号写作技能为例展示了具体配置。文章还提供了技能优先级切换的实用技巧,帮助用户灵活管理不同版本的技能。

海兰 239

QT学习c++基础之lambda与内敛函数区别

内联函数 相当于把几个语句封装成一个函数,在不执行时不分配空间,调用时相当于这几条语句是放在这里的但用函数调用的方式。// 编译器可能会将此替换为:int result = 5 + 3;//这种方式是把上面全部参数引用过来,相当于指针,直接访问地址,可以修改参数。//这种方式不能修改xy的值,只有可读权限。//这种方式是把上面全部参数捕获过来。lambda参数捕获案例。

weixin_48691620的博客 223

YOLO11改进|卷积篇|引入多样化分支块DBB

YOLO11中添加多样化分支块DBB

A1983Z的博客 1449

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

C++Cherno 学习笔记day15 [57]-[60] 静态数组、函数指针、lambda、using namespace std

Lambda 表达式是现代 C++ 中提升代码表达力的利器,尤其适合以下场景:短小的一次性逻辑(如 STL 算法中的谓词)。需要捕获上下文的闭包(如异步回调、状态保存)。替代传统的函数对象(减少样板代码)。

Shirleyyy1的博客 1157

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

C++11新宠-Lambda函数学习

Lambda背景 Lambda来自lambda calculus(λ演算,如果有兴趣,可以看这篇文章http://cgnail.github.io/academic/lambda-1/)——一种定义和应用函数的数学系统。 Lambda 表达式之所以是 C++ 11 新增特性中最激动人心的一个,究其原因是其在距离、简洁、效率和功能上都让人耳目一新。引入的主要目的是让你能够将类似于函数的表达式用作接受函

尚小馨的博客 1107

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

c++中function和lambda函数的学习

fun是一个通用的函数封装器,可以用于存储、传递和调用任何可调用对象,如函数、函数指针、成员函数指针、lambda 表达式等。当std::function对象实例未包含任何实际可调用实体时,调用该std::function对象实例将抛出std::bad_function_call异常。Lambda表达式是c++语言的一个重要特性,它可以作为函数对象使用,可以用来替代一些繁琐的函数声明和定义。的模板参数是函数的签名,即函数的参数类型和返回类型。{ function body }是表达式的函数体,在应用中必填。

段一的博客 442

c++lambda函数学习笔记

//Lambda 函数与表达式 //C++11 提供了对匿名函数的支持, 称为 Lambda 函数(也叫 Lambda 表达式)。 //Lambda 表达式把函数看作对象。Lambda 表达式可以像对象一样使用, // 比如可以将它们赋给变量和作为参数传递,还可以像函数一样对其求值。 //Lambda 表达式本质上与函数声明非常类似。 #include using namespace std; class test { public: void hello() { cout << “test h

weixin_51235620的博客 178

长假别猛学新框架:先把你已有的技术基建收拾好

长假期间,技术人常见的难题是既想学习,又面临碎片化时间或多设备切换的干扰。要解决这一问题,关键不在于扩大学习范围,而在于理解任务类型与环境是否匹配——环境配置、脚本固化、备份验证这类“基建型任务”具有中断成本低、产出可复用的特点,恰好适合在出行频繁的假期推进。利用dotfiles管理配置环境,借助SSH打通远程开发链路,再对自建服务做一次巡检与备份恢复演练,都能显著提升开发基础环境的确定性。即使身处多座城市之间往返,也能通过固定流程完成高效运维。当环境可重建、数据可恢复、经验可检索时,假期积累的资产自然会延

weixin_34242819的博客 320

C++ lambda函数用法 [学习笔记]

C++ 的(也称为匿名函数)是一种轻量级的函数定义方式,可以嵌入代码中并传递给其他函数。

rygwang的博客 552

【C++学习笔记】C++ lambda函数 及mutable

mutable修饰符用来指明我们可以对const的变量进行修改,同样,在lambda函数中,也可以使用此修饰符。 按值捕获到lambda函数中的变量在函数体中默认是const类型,即不可修改,在添加了mutable修饰符后,便可以对此变量进行修改,但此时仍然修改的是位于lambda函数体中的局部变量,具体的用处类似于函数体中的static变量,只允许在该函数中改变。 int n {}; // 使用mutable时,参数列表“()”是不可以省略的 auto fun = [n] () mutable {.

qq_42961603的博客 783
上一篇: C++ 编译报错discards qualifiers [-fpermissive]
下一篇: 聊聊Linux中的线程本地存储(1)——什么是TLS
killmice
博客等级 码龄14年 119粉丝 54原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值