C++——Lambda函数
4、Lambda函数
lambda 表达式可以说是 c++11 引用的最重要的特性之一, 它定义了一个匿名函数, 可以捕获一定范围的变量在函数内部使用,
一般有如下语法形式:
auto func = [capture] (params) opt -> ret { func_body; };
其中 func 是可以当作 lambda 表达式的名字,作为一个函数使用,capture 是捕获列表,params 是参数表,opt: 不需要可以省略。 (mutable: 可以修改按值传递进来的拷贝(注意是能修改拷贝,而不是值本身)exception: 指定函数抛出的异常,如抛出整数类型的异常,可以使用 throw ()
), ret 是返回值类型,func_body 是函数体。
示例
auto func1 = [](int a) -> int { return a + 1; };
auto func2 = [](int a) { return a + 2; };
cout << func1(1) << " " << func2(2) << endl;
捕获列表:
[] | 不捕捉任何变量 |
---|---|
[&] | 捕获外部作用域中所有变量,并作为引用在函数体内使用 (按引用捕获) |
[=] | 捕获外部作用域所有变量,在函数内内有个副本使用,拷贝的副本在匿名函数体内部是只读的 |
[=,&foo] | 按值捕获外部作用域中所有变量,并按照引用捕获外部变量 foo |
[bar] | 按值捕获 bar 变量,同时不捕获其他变量 |
[&bar] | 按引用捕获 bar 变量,同时不捕获其他变量 |
[this] | 捕获当前类中的 this 指针,让 lambda 表达式拥有和当前类成员函数同样的访问权限,如果已经使用了 & 或者 =, 默认添加此选项 |
示例:
#include <iostream>
#include <functional>
using namespace std;class Test
{public:void output(int x, int y){//auto x1 = [] {return m_number; }; // errorauto x2 = [=] {return m_number + x + y; }; // okauto x3 = [&] {return m_number + x + y; }; // okauto x4 = [this] {return m_number; }; // ok//auto x5 = [this] {return m_number + x + y; }; // errorauto x6 = [this, x, y] {return m_number + x + y; }; // okauto x7 = [this] {return m_number++; }; // ok}int m_number = 100;
};
x1 | 错误,没有捕获外部变量,不能使用类成员 m_number |
---|---|
x2 | 正确,以值拷贝的方式捕获所有外部变量 |
x3 | 正确,以引用的方式捕获所有外部变量 |
x4 | 正确,捕获 this 指针,可访问对象内部成员 |
x5 | 错误,捕获 this 指针,可访问类内部成员,没有捕获到变量 x,y,因此不能访问。 |
x6 | 正确,捕获 this 指针,x,y |
x7 | 正确,捕获 this 指针,并且可以修改对象内部变量的值 |
示例:
int main(void)
{int a = 10, b = 20;// auto f1 = [] {return a; }; // errorauto f2 = [&] {return a++; }; // okauto f3 = [=] {return a; }; // ok// auto f4 = [=] {return a++; }; // error// auto f5 = [a] {return a + b; }; // errorauto f6 = [a, &b] {return a + (b++); }; // okauto f7 = [=, &b] {return a + (b++); }; // okreturn 0;
}
f1 | 错误,没有捕获外部变量,因此无法访问变量 a |
---|---|
f2 | 正确,使用引用的方式捕获外部变量,可读写 |
f3 | 正确,使用值拷贝的方式捕获外部变量,可读 |
f4 | 错误,使用值拷贝的方式捕获外部变量,可读不能写 |
f5 | 错误,使用拷贝的方式捕获了外部变量 a,没有捕获外部变量 b,因此无法访问变量 b |
f6 | 正确,使用拷贝的方式捕获了外部变量 a,只读,使用引用的方式捕获外部变量 b,可读写 |
f7 | 正确,使用值拷贝的方式捕获所有外部变量以及 b 的引用,b 可读写,其他只读 |
返回值:
很多时候,lambda 表达式的返回值是非常明显的,因此在 C++11 中允许省略 lambda 表达式的返回值。
// 完整的lambda表达式定义
auto f = [](int a) -> int
{return a+10;
};// 忽略返回值的lambda表达式定义
auto f = [](int a)
{return a+10;
};
一般情况下,不指定 lambda 表达式的返回值,编译器会根据 return 语句自动推导返回值的类型,但需要注意的是 labmda表达式不能通过列表初始化自动推导出返回值类型
。
// ok,可以自动推导出返回值类型
auto f = [](int i)
{return i;
}// error,不能推导出返回值类型
auto f1 = []()
{return {1, 2}; // 基于列表初始化推导返回值,错误
}
函数本质:
使用 lambda 表达式捕获列表捕获外部变量,如果希望去修改按值捕获的外部变量,那么应该如何处理呢?这就需要使用 mutable 选项,被mutable修改是lambda表达式就算没有参数也要写明参数列表,并且可以去掉按值捕获的外部变量的只读(const)属性。
int a = 0;
auto f1 = [=] {return a++; }; // error, 按值捕获外部变量, a是只读的
auto f2 = [=]()mutable {return a++; }; // ok
最后再剖析一下为什么通过值拷贝的方式捕获的外部变量是只读的:
lambda表达式的类型在C++11中会被看做是一个带operator()的类,即仿函数。
按照C++标准,lambda表达式的operator()默认是const的,一个const成员函数是无法修改成员变量值的。
mutable 选项的作用就在于取消 operator () 的 const 属性。
因为 lambda 表达式在 C++ 中会被看做是一个仿函数,因此可以使用std::function和std::bind
来存储和操作lambda表达式:
#include <iostream>
#include <functional>
using namespace std;int main(void)
{// 包装可调用函数std::function<int(int)> f1 = [](int a) {return a; };// 绑定可调用函数std::function<int(int)> f2 = bind([](int a) {return a; }, placeholders::_1);// 函数调用cout << f1(100) << endl;cout << f2(200) << endl;return 0;
}
对于没有捕获任何变量的 lambda 表达式,还可以转换成一个普通的函数指针:
using func_ptr = int(*)(int);
// 没有捕获任何外部变量的匿名函数
func_ptr f = [](int a)
{return a;
};
// 函数调用
f(1314);
参考:爱编程的大丙
C++ prime_plus第六版
程序喵大人
C++——Lambda函数相关推荐
- Java箭头函数,lambda函数
Java箭头函数,lambda函数 lambda表达式实质就是一种语法糖,(建议尽量不要使用lambda表达式,代码太简洁,难懂,难以调试) lambda表达式的简单例子: 不需要参数,返回5 ()- ...
- Python 精选笔试面试习题—sorted 与 sort 单例模式、统计字符个数Count、垃圾回收、lambda函数、静态方法、类方法、实例方法、分布式锁、
1. 字典根据键从小到大排序? In[38]: dic = {"name": "Tom", "age": 30, "country ...
- C++:Lambda函数学习
C++:Lambda函数学习 该文章转载自caimagic的博客:https://www.cnblogs.com/langzou/p/5962033.html 或许,Lambda 表达式算得上是 C+ ...
- aws lambda_为什么我会自动删除所有旧的推文以及我用来执行此操作的AWS Lambda函数...
aws lambda From now on, my tweets are ephemeral. Here's why I'm deleting all my old tweets, and the ...
- pandas使用apply函数和lambda函数、把所有行指定的数据列进行相加(use apply and lambda to add value in dataframe rows)
pandas使用apply函数和lambda函数.把所有行指定的数据列进行相加(use apply and lambda to add value in dataframe rows) 目录
- pandas新字段(数据列)生成、使用np.where或者apply lambda函数结合if else生成新的字段,详解及实战
pandas新字段(数据列)生成.使用np.where或者apply lambda函数结合if else生成新的字段,详解及实战 pandas apply用法: pandas apply方法的作用原理 ...
- lambda函数详解
lambda函数的作用就是可以编写内嵌的无名函数,而不必写成独立的函数: 结构:[]为开始,(参数){函数体} 例如: 1. auto lambdaFun1 = [](int a) {std::cou ...
- python中多重if语句用法_python – 在Pandas中使用Apply使用多个if语句的Lambda函数
我试图根据像这样的数据框中的人的大小来推断分类: Size 1 80000 2 8000000 3 8000000000 ... 我希望它看起来像这样: Size Classification 1 8 ...
- python lambda函数_python入门基础之lambda匿名函数
lambda的一般形式是关键字lambda后面跟一个或多个参数,紧跟一个冒号,以后是一个表达式.lambda是一个表达式而不是一个语句.它能够出现在Python语法不允许def出现的地方.作为表达式, ...
最新文章
- 5.1.3.jvm java虚拟机系统参数查看
- CvArr、Mat、CvMat、IplImage、BYTE转换(总结而来)
- BGWN项目轶事之主导Global Weekly Meeting
- 销量赶超娇兰、SK-II的林清轩,能带领国产护肤品奔赴高端化吗?
- 一起教育科技递交招股书:收入增速超277.48%,或成纳斯达克最大教育概念股
- Centos7设置Tomat开机自启
- 荣耀play一直显示无服务器,降价都无法补救?荣耀Play3:绝不是电子垃圾!
- 让软件自己写软件,英特尔的机器编程会取代程序员吗?
- 水很深的深度学习-Task02机器学习基础
- 科技公司钟爱的50款开源工具
- 算法:平衡二叉树110. Balanced Binary Tree
- 多线程有几种实现方法_Java多线程实现有哪几种方法?
- lavaral中文手册_Laravel 5.8 中文文档手册
- 值得收藏,学术论文投稿前必看,最全准备材料~
- C++、C#、Java、Python、可以获取L2行情实时数据吗?
- JavaScript|日期格式化、今天、昨天、明天和某天
- 考研复试问答(计算机组成原理部分)
- matplotlib绘图散点图可用的markers形状(标记)汇总
- [附源码]计算机毕业设计JAVA社区健康服务平台管理系统lunwen
- Django实现短信注册功能
热门文章
- SCI写作|Tweet转发最多的好文之一:写好结构化论文(背景-内容-结论)的十条规则!...
- 北京、广州同时开课 | 临床基因组学数据分析实战助力解析Case,快速发表文章...
- Nature:复杂菌群空间分布研究
- Nature综述:植物与微生物组的相互作用:从群落装配到植物健康(上)
- CHM综述:建立因果关系,合成菌群在植物菌群研究中的机会
- Nature:首个肠道微生物对药物代谢影响的系统性研究
- PNAS-2018-多年多点5千样本鉴定玉米根际可遗传微生物
- java表驱动法索引访问_表驱动法 - SegmentFault 思否
- R语言ggplot2可视化:ggplot2可视化水平堆叠条形图、并且在每个堆叠条形图的内部居中添加百分比文本标签信息
- R语言dataframe数据列格式转换(从整型integer转化为浮点型float)