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函数相关推荐

  1. Java箭头函数,lambda函数

    Java箭头函数,lambda函数 lambda表达式实质就是一种语法糖,(建议尽量不要使用lambda表达式,代码太简洁,难懂,难以调试) lambda表达式的简单例子: 不需要参数,返回5 ()- ...

  2. Python 精选笔试面试习题—sorted 与 sort 单例模式、统计字符个数Count、垃圾回收、lambda函数、静态方法、类方法、实例方法、分布式锁、

    1. 字典根据键从小到大排序? In[38]: dic = {"name": "Tom", "age": 30, "country ...

  3. C++:Lambda函数学习

    C++:Lambda函数学习 该文章转载自caimagic的博客:https://www.cnblogs.com/langzou/p/5962033.html 或许,Lambda 表达式算得上是 C+ ...

  4. 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 ...

  5. 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) 目录

  6. pandas新字段(数据列)生成、使用np.where或者apply lambda函数结合if else生成新的字段,详解及实战

    pandas新字段(数据列)生成.使用np.where或者apply lambda函数结合if else生成新的字段,详解及实战 pandas apply用法: pandas apply方法的作用原理 ...

  7. lambda函数详解

    lambda函数的作用就是可以编写内嵌的无名函数,而不必写成独立的函数: 结构:[]为开始,(参数){函数体} 例如: 1. auto lambdaFun1 = [](int a) {std::cou ...

  8. python中多重if语句用法_python – 在Pandas中使用Apply使用多个if语句的Lambda函数

    我试图根据像这样的数据框中的人的大小来推断分类: Size 1 80000 2 8000000 3 8000000000 ... 我希望它看起来像这样: Size Classification 1 8 ...

  9. python lambda函数_python入门基础之lambda匿名函数

    lambda的一般形式是关键字lambda后面跟一个或多个参数,紧跟一个冒号,以后是一个表达式.lambda是一个表达式而不是一个语句.它能够出现在Python语法不允许def出现的地方.作为表达式, ...

最新文章

  1. 5.1.3.jvm java虚拟机系统参数查看
  2. CvArr、Mat、CvMat、IplImage、BYTE转换(总结而来)
  3. BGWN项目轶事之主导Global Weekly Meeting
  4. 销量赶超娇兰、SK-II的林清轩,能带领国产护肤品奔赴高端化吗?
  5. 一起教育科技递交招股书:收入增速超277.48%,或成纳斯达克最大教育概念股
  6. Centos7设置Tomat开机自启
  7. 荣耀play一直显示无服务器,降价都无法补救?荣耀Play3:绝不是电子垃圾!
  8. 让软件自己写软件,英特尔的机器编程会取代程序员吗?
  9. 水很深的深度学习-Task02机器学习基础
  10. 科技公司钟爱的50款开源工具
  11. 算法:平衡二叉树110. Balanced Binary Tree
  12. 多线程有几种实现方法_Java多线程实现有哪几种方法?
  13. lavaral中文手册_Laravel 5.8 中文文档手册
  14. 值得收藏,学术论文投稿前必看,最全准备材料~
  15. C++、C#、Java、Python、可以获取L2行情实时数据吗?
  16. JavaScript|日期格式化、今天、昨天、明天和某天
  17. 考研复试问答(计算机组成原理部分)
  18. matplotlib绘图散点图可用的markers形状(标记)汇总
  19. [附源码]计算机毕业设计JAVA社区健康服务平台管理系统lunwen
  20. Django实现短信注册功能

热门文章

  1. SCI写作|Tweet转发最多的好文之一:写好结构化论文(背景-内容-结论)的十条规则!...
  2. 北京、广州同时开课 | 临床基因组学数据分析实战助力解析Case,快速发表文章...
  3. Nature:复杂菌群空间分布研究
  4. Nature综述:植物与微生物组的相互作用:从群落装配到植物健康(上)
  5. CHM综述:建立因果关系,合成菌群在植物菌群研究中的机会
  6. Nature:首个肠道微生物对药物代谢影响的系统性研究
  7. PNAS-2018-多年多点5千样本鉴定玉米根际可遗传微生物
  8. java表驱动法索引访问_表驱动法 - SegmentFault 思否
  9. R语言ggplot2可视化:ggplot2可视化水平堆叠条形图、并且在每个堆叠条形图的内部居中添加百分比文本标签信息
  10. R语言dataframe数据列格式转换(从整型integer转化为浮点型float)