lambda表达式定义一个匿名函数,并能捕获一定范围内的变量,语法如下:
[capture] (paras) opt -> ret {body;}
capture:捕获列表 ,捕获一定范围内的变量
[] - 不捕捉任何变量
[&] - 捕捉所有变量,并作为引用在函数体内使用(按引用捕获)
[=] - 捕捉所有变量,并作为副本在函数体内使用(按值捕获-拷贝的副本在匿名函数内部是只读的)
[=,&foo] - 按值捕获所有(除foo外)变量,并按引用捕获foo
[=bar] - 只按值捕获bar变量
[&bar] - 只按引用捕获bar变量
[this] - 捕获当前类的this指针(和类成员函数相同的访问类权限;如原来有&或者=,默认添加此选项)
class LamTest
{
public:
void fun(int x,int y) {
//申明匿名函数,没有调用,如需调用,需要在{}外加上()
//auto f1 = [] {return m_num;};//不捕捉x y m_num(错误)
//auto f2 = [] (){return m_num;};//不捕捉x y m_num( 错误)
auto f3 = [=] {return m_num + x + y;};//按值捕捉所有变量(只读)x y m_num
auto f4 = [&] {return m_num + x + y;};//按引用捕捉x y m_num
auto f5 = [this] {return m_num;};//只捕获类中的成员变量捕捉m_num
auto f6 = [this] {return m_num++;};//只捕获类中的成员变量捕捉m_num
//auto f7 = [this] {return m_num + x + y;};//只捕获类中的成员变量捕捉m_num,没有捕捉x y(错误)
auto f8 = [this,x,y] {return m_num + x + y; };//捕获类中的成员变量捕捉m_num,并捕捉x y
}
int m_num = 100;
};
paras:参数列表,如普通函数一样,没有可以不写
auto f = [](){return 1;};//没有参数,参数列表为空
auto f = []{return 1;};//没有参数,参数列表省略
opt:函数选项 ,不需要可以省略
//mutable:可以修改按值传递进来的拷贝(修改的是拷贝进来的,而不是变量本身)
//exception:指定函数抛出异常,可以使用throw()
void test_lambda(int x,int y) {
int a = 2;
int b = 22;
//z与实参100对应,没有形参,也不需要输入实参
//调用需要在{}外加上()
//mutable与++b对应,lambda里面的拷贝的b只读,加上mutable可以修改lambda里面的值,外面的b没有修改
//使用mutable时,没有参数也要把空的参数列表()加上
[=,&x] (int z) mutable{
int c = a;
int d = x;
++b;
cout << "lambda b = " << b << endl;
}(100);
cout << "lambda b = " << b << endl;
}
ret:返回类型,c11中通过返回值后置来设置返回值类型
// 一般可以省略,能自动推导除返回值类型
// 不能推导出返回值为初始化列表,需要下显式添加返回值类型
body:函数体,不能省略,但是可以为空
class LamTest
{
public:
void fun(int x,int y) {
//申明匿名函数,没有调用,如需调用,需要在{}外加上()
//auto f1 = [] {return m_num;};//不捕捉x y m_num(错误)
//auto f2 = [] (){return m_num;};//不捕捉x y m_num( 错误)
auto f3 = [=] {return m_num + x + y;};//按值捕捉所有变量(只读)x y m_num
auto f4 = [&] {return m_num + x + y;};//按引用捕捉x y m_num
auto f5 = [this] {return m_num;};//只捕获类中的成员变量捕捉m_num
auto f6 = [this] {return m_num++;};//只捕获类中的成员变量捕捉m_num
//auto f7 = [this] {return m_num + x + y;};//只捕获类中的成员变量捕捉m_num,没有捕捉x y(错误)
auto f8 = [this,x,y] {return m_num + x + y; };//捕获类中的成员变量捕捉m_num,并捕捉x y
}
int m_num = 100;
};
lambda表达式优点:
1.简洁(避免了代码膨胀和功能分散)
2.声明的编程式风格(就地匿名定义函数目标或函数对象,不需要额外写一个命名函数
或函数对象)
3.灵活(在需要的时间地点实现函数的闭包)
值拷贝(=)时注意:
1.lamda表达式被看做一个带有operator()的类,即仿函数
2. mutable时取消参数的const属性
3. 可以使用std::function与std::bind来保存、操作
//对于没有捕获任何变量的lambda表达式,可以转换成一个普通函数指针
using lamdaPtr = void(*)(int);
lamdaPtr f = [](int a) {
cout << "普通函数指针 a = " << a << endl;
};
//函数调用
f(999);
//对于值拷贝的lambda表达式,是个仿函数可以使用std::function与std::bind来保存、操作
//std::function
function<void(int)> fp = [=](int a) {
cout << "包装器 a = " << a << endl;
};
fp(753);
//std::bind
//fp2可调用对象
function<void(int)> fp2 = bind([=](int a) {
cout << "绑定器 a = " << a << endl;
}, placeholders::_1);
fp2(248);
//fb仿函数
auto fb = bind([=](int a) {
cout << "绑定器 a = " << a << endl;
}, placeholders::_1);
fb(666);