简介
lamda表达式是C++11中使用最频繁的特性之一。主要是其比较灵活易用。lamda表达式主要有以下特点:1、声明式的编程风格,匿名定义目标函数和对象,不需要再重新写一个函数;2、避免代码膨胀和分散;3、在需要的时间和地点实现功能闭包,程序更灵活。
用法
语法:
[capture](params)opt -> ret {//func;}
capture是捕获列表
params是函数参数
opt是函数选项
ret是返回值
func是函数体
捕获列表:
lamda表达式的捕获列表可以捕获一定范围内的变量
- [] : 表示不捕获任何的变量
- [&] : 表示按引用捕获,就是会捕获外部作用域的所有变量,当作引用传递进lamda表达式
- [=] : 表示按值捕获,就是会捕获外部作用域的所有变量,当作值传递进lamda表达式。拷贝的值在lamda表达式中是只读的
- [=, &foo] : 按值捕获外部作用域的所有变量,按引用捕获foo
- [bar] : 按值捕获bar,同时不捕获其他的变量
- [&bar] : 按引用捕获bar,同时不捕获其他的变量
- [this] : 捕获当前类的this指针,如果是已经使用了&,=,默认就会加上这个捕获选项
params:
参数的使用方法和正常的函数没什么区别,当参数个数为0的时候,可以直接把()省略。
auto func = [](){return 0;}
auto func = []{return 0;}
函数选项:
mutable:可以修改按值传递进来的拷贝
exception:值函数可以抛出异常,可以使用throw抛出整数类的异常
ret
返回值一般可以 直接自动推导出返回值,但是返回的是一个初始化列表的时候,就无法自动推导了,需要手动的写上返回值类型。
在这里插入代码片
函数体都和正常的函数没什么区别,这里就不多赘述。
举例:
class A
{
public:
void test(int x, int y) {
auto a1 = []{return mnt;} // error, 捕获列表没写捕获外部变量
auto a2 = [=]{return mnt + x + y;} // ok
auto a3 = [&]{return mnt + x + y;} // ok
auto a4 = [this]{return mnt;} // ok
auto a5 = [this]{return mnt + x + y;} // error,只捕获了this,并没有其他的x,y变量
auto a6 = [this, x, y]{return mnt + x + y;} // ok
auto a7 = [this]{return mnt++;} // ok
auto a8 = [=]{return x++;} // error,拷贝值的时候,拷贝进去的值无法改变
auto a9 = [=]()mutable{return x++;} // error,拷贝值的时候,拷贝进去的值无法改变,加上mutable表示可以改变值传递的值
}
private:
int mnt = 0;
};
本质
lamda表达式在c++11中被看做是一个带operator()的类,即仿函数。
按照c++11的标准,operator()默认是const类型,一个const成员函数无法修改成员变量的值,mutable的目的就在于消除const属性。
并且对于没有捕获任何变量的lamda表达式,就可以当做是一个函数指针来使用。如果捕获了变量的话就只能作为一个仿函数使用。
void test(int a, int b)
{
using ptr = void(*)(int);
ptr p1 = [](int x) {
cout << x << endl;
};
p1(1);
ptr p2 = [=](int x) {
cout << x << endl;
}; // error 此时捕获列表不为空不能当做函数指针来使用
function<void(int)> func1 = [=](int x) {
cout << x << endl;
}; // ok
func1(2);
}