lambda函数简介
lambda函数是C++11标准新增的语法,也称为lambda表达式或匿名函数。
lambda函数的特点是:距离近、简洁、高效和功能强大。
优点
声明式编程风格:就地匿名定义目标函数或函数对象,有更好的可读性和可维护性。
简洁:不需要额外写一个命名函数或函数对象,,避免了代码膨胀和功能分散。
更加灵活:在需要的时间和地点实现功能闭包。
基本用法
[caoture] (params) opt -> ret {body;};
[捕获列表] (参数列表) 函数选型 -> 返回类型 {函数体} ;
注意
opt选项:
mutable:可以修改按值传递进来的拷贝(注意是能修改拷贝,而不是值本身)
exception: 指定函数抛出的异常,如抛出整数类型的异常,可以使用 throw ();
void test4()
{
auto f = [](int a) -> int {return a + 1; };
//捕获列表
cout << f(1) << endl;
}
参数列表
参数列表是可选的,类似普通函数的参数列表,如果没有参数列表,()可以省略不写。
与普通函数的不同:
1. lambda函数不能有默认参数。
2. 所有参数必须有参数名。
3. 不支持可变参数。
返回类型
用后置的方法书写返回类型,类似于普通函数的返回类型,如果不写返回类型,编译器会根据函数体中的代码推断出来。
如果有返回类型,建议显式的指定,自动推断可能与预期不一致。
函数体
和普通函数的函数体一样
捕获列表
通过捕获列表,lambda函数可以访问父作用域中的非静态局部变量(静态局部变量可以直接访问,不能访问全局变量)。
捕获列表书写在[]中,与函数参数的传递类似,捕获方式可以是值和引用。
以下列出了不同的捕获列表的方式。
补充:
[ this ] --捕获当前类的this指针,让lambda表达式拥有和当前类成员函数同样的访问权限
分别使用值捕获和引用捕获
void test()
{
int a = 1;
double b = 2.2;
auto f1 = [](int a)
{
cout << "a=" << a << endl;
};
auto f2 = [&](double m)->double
{
m++;
return m;
};
f1(a);
cout << "b=" << f2(b) << endl;
}
隐式捕获
void test_2()
{
int a = 1;
double b = 2.3;
auto f1 = [=]
{
cout << "a=" << a << ", b=" << b << endl;
cout << "a=" << ++a << ", b=" << ++b << endl;
};
auto f2 = [&]
{
cout << "a=" << a << ", b=" << b << endl;
cout << "a=" << ++a << ", b=" << ++b << endl;
};
f2();
f1();
}
混合方式捕获
lambda函数还支持混合方式捕获,即同时使用显式捕获和隐式捕获。
混合捕获时,捕获列表中的第一个元素必须是 = 或 &,此符号指定了默认捕获的方式是值捕获或引用捕获。
需要注意的是:显式捕获的变量必须使用和默认捕获不同的方式捕获。
修改值捕获变量的值
在lambda函数中,如果以传值方式捕获变量,则函数体中不能修改该变量,否则会引发编译错误。
在lambda函数中,如果希望修改值捕获变量的值,可以加mutable选项,但是,在lambda函数的外部,变量的值不会被修改。
void test_4()
{
int a = 123;
auto f = [a]()mutable { cout << ++a << endl; }; // 不会报错
cout << a << endl; // 输出:123
f(); // 输出:124
cout << a << endl; // 输出:123
}
函数本质
使用lambda表达式捕获列表外部变量,如果希望去修改按值捕获的外部变量,那么应该如何处理呢?这就要使用mutable选项,被mutable修改是lambda表达式就算没有参数也要写明参数列表,并且可以去掉按值捕获的外部变量的只读(const)属性。
#include<iostream>
using namespace std;
int main()
{
int a = 10;
auto f1 = [=] {++a; return a; }; //错误
auto f2 = [=]()mutable {++a; return a; }; //正确
auto f3 = [&] {++a; return a; }; //正确
return 0;
}
通过按值捕获的变量是只读的,按引用捕获的可以修改,而mutable可以去除按值捕获const的特点。
lambda表达式在c++中被视为一个仿函数