匿名函数lambda表达式
Java8中提供了类似的特性。C++在C++11中提供了该特性。使用lambda表达式的好处实现了无名函数,对于程序员而言少了费脑子想函数名称的困扰。从可读性而言简洁不少,只关注函数的具体实现。在C++并发编程中,作为std::condition_variable::wait()的参数,或是作为参数传入线程的构造函数等。
完整的lambda表达是如下所示,
[ capture ] ( params ) mutable exception attribute -> ret { body }
用[]括起来的部分是表达式体内从外部可以捕获的内容(在下面再讲),用()括起来的部分是函数体使用的参数,ret代表返回值类型,{}括起来的部分是可执行函数体。三个关键字:
mutable lambda表达式中按照拷贝方式获取值,如果要修改该拷贝值,需要添加mutable关键字,因为lambda表达式重载的operator() 是const的。按引用传递则不需要加上该关键字。
exception 代表lambda表达式是否抛出异常,如noexcept不抛出异常。
attribute attribute的出现是为了设置函数属性、变量属性和类型属性。attribute的格式“__attribute__ ((attribute-list))”。属性如nonreturn(函数无返回,编译器不用设置相关代码),packed(编译器不按照优化对齐)可以从gcc手册中查找。
函数中截取变量
lambda表达式理解的关键点在于如何通过描述[]里的内容控制了从外部获取变量,捕获的变量可以在函数体内使用。
- 空的[]代表不获取任何外部变量。
- [this] 代表获取获得执行环境内的this指针。
- [&X, Y] C++通过拷贝和引用的方式传递参数。&代表使用引用传递,而没有&则使用拷贝方式传递。
-[&] 捕获外部作用域的所有变量,并通过引用方式使用,
-[=] 捕获外部作用域的所有变量,并通过拷贝方式使用。拷贝过程在创建时拷贝,而非在调用时。
另外,lambda表达式不可以赋值,出现在等号的左边。
学习lambda表达式可以多找找相关的代码片段,看多了看到一个[]就会反应是lambda表达式。比如
auto add = [](int a, int b){ return a+b;}
add(100,200);
看到有些会在定义线程时使用lambda表达式。如下所示
upkeeper = std::thread([this]() { ... }