说明
Lambda 表达式(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。
格式
[capture list] (parameter list) ->return type {function body}
例子
#include <stdio.h>
#include <string>
#include <functional>
#include <memory>
static int g_var = 1;
class Widget
{
public:
Widget()
{
printf("widget\n");
}
Widget(const Widget& )
{
printf("copy widget\n");
}
~Widget()
{
printf("~widget\n");
}
void test() const
{
printf("widget test\n");
}
void test1() const
{
printf("widget test1\n");
}
};
int main()
{
//[capture list] (parameter list) ->return type {function body}
//1.完整的例子
{
auto fun = [](int a,int b)->int{return a+b;};
//输出30
printf("%d\n",fun(10,20));
}
//2.可以忽略参数列表 和 返回值. 如果有返回值,则自动推导类型,否则为void
{
auto fun=[]{return 40;};
//输出40
printf("%d\n",fun());
}
//3.使用捕获列表例子
{
int var = 50;
auto fun = [var]{return var+1;};
//输出51
printf("%d\n",fun());
}
//3.1值捕获,即lambda创建时拷贝 但是不能在在lambda函数体内修改值
{
int var = 40;
int var1 = 60;
//值拷贝 捕获
auto fun = [var,var1]
{
//var = 1; 错误 不能改值
return var+var1;
};
var = 10;
var1 = 20;
//输出100
printf("%d\n",fun());
}
//3.2 引用捕获,即lambda创建时采用引用方式捕获,引用捕获应保证变量在lambda没执行完前不能消失
{
int var = 40;
int var1 = 60;
//var采用引用方式捕获 var1采用拷贝捕获
auto fun = [&var,var1]{return var+var1;};
var = 10;
var1 = 20;
//输出70
printf("%d\n",fun());
}
//3.3 隐式值捕获 编译器根据lambda中的代码自动推导
{
int var = 80;
auto fun = [=]{return var;};
//输出80
printf("%d\n",fun());
}
//3.3 隐式引用捕获 编译器根据lambda中的代码自动推导
{
int var = 80;
auto fun = [&]{return var;};
var = 90;
//输出90
printf("%d\n",fun());
}
//3.4 混合引用 显式捕获和隐士捕获必须使用不同的方式,即不能同时为值捕获或者引用捕获
{
std::string str("10");
int var = 90;
auto fun = [=,&str]{return (atoi(str.c_str()) + var);};
//输出100
printf("%d\n",fun());
}
//3.5使用值捕获,加上mutable就可以在lambda函数体内修改值
{
int var = 50;
auto fun = [var]()mutable{ var=110; return var;};
//输出 50 110
printf("%d %d\n",var,fun());
}
//3.6使用引用捕获,是否可以修改依赖于是否有const修饰
{
int var = 50;
const int var1 = 60;
auto fun = [&]{
var=120;
// var1 = 130; const 不能修改
return var;
};
//输出 120 120 60
printf("%d %d %d\n",var,fun(),var1);
}
//3.6 static值不能被捕获
// lambda 不仅依赖局部变量和形参(它们能被捕获)
// 还依赖静态存储期 即定义在全局或名字空间作用域中 类 函数等 以 static修饰 这样的对象可以在lambda 中使用 但不能捕获
{
static int var = 50;
int var1 = 70;
//var 不能被捕获,var1值被拷贝捕获了
auto fun = [=]{
return var+var1+g_var;
};
//错误 var不能被捕获
// auto fun1 = [var,var1]{
// return var+var1;
// };
//错误 var不能被捕获
// auto fun2 = [&var,var1]{
// return var+var1;
// };
//输出 50 121
printf("%d %d\n",var,fun());
var = 60;
g_var = 2;
//输出 60 132
printf("%d %d\n",var,fun());
}
printf("-----------------------------\n");
//对象值捕获
{
Widget w;
//调用拷贝构造函数
auto fun= [=]{w.test();}; // test 必须是const
fun();
}
printf("-----------------------------\n");
//对象引用捕获
{
Widget w;
auto fun= [&]{w.test1();};
fun();
}
printf("-----------------------------\n");
//移动捕获
{
Widget w ;
auto fun = std::bind(
[]( Widget& w){w.test1();},
std::move(w)
);
fun();
}
//转换为函数指针
{
int (*fun)(int, int)=[](int a,int b){return a+b;};//不捕获时才可转换为函数指针
printf("%d\n",fun(1,2));
}
return 0;
}