C++中的Lambda表达式
Lambda表达式结构
本质是函数
完整结构:
[capture list](params list) mutable exception ->return type{
function body
};
其中,各个内容的含义:
- capture list:捕获列表,捕获表达式外部的变量,相当于函数传参一样
- params list:参数列表,该表达式可接收的参数,可省略(当表达式不需要外部传参的时候)
- mutable:用来指定表达式可以修改捕获变量的值,需要时才添加
- exception:异常设定
- return type:表达式的返回类型,相当于函数的返回值类型一样(可省略,当表达式内部不返回任何值的时候)
- function body:跟函数体一样,也就是函数实现
但是表达式,需要一个返回值指向这个表达式,也就是函数指针。通常我们采用auto直接指向,省事。
auto func_ptr = [capture list](params list) mutable exception ->return type{
function body
};
然后,我们调用这个表达式的时候,就像函数一样:需要传入参数列表
retun type value = func_ptr(params list)
比如,举一个简单的例子:
int a = 10;
int b = 20;
auto Lambda = [a,b](int para1,int para2)mutable->int {
a = a + para1;
b = b + para2;
return a + b;
};
cout << Lambda(1, 1) << endl; //32
把mutable去掉,在表达式内部就不可以修改a或b的值。如果我在函数内部并没有修改a的值,那么mutable就可以省略,如果有修改捕获值的需求,那就得需要加上mutable。
如果真的想修改a或者b的值,且不想用mutable,那就得采用引用传递了。
auto Lambda = [&a,&b](int s,int v)->int {
a = a + s;
b = b + v;
return a + b;
};
//不用auto的话,就得这么写,交代函数指针的类型
//int (*Lambda)(int,int) 这叫指向函数的指针,必须说明参数列表
int (*Lambda)(int,int) = [&a,&b](int s,int v)->int {
a = a + s;
b = b + v;
return a + b;
};
因为,表达式中的捕获列表默认采用的值传递,也就是说不加引用不加mutable,是直接将a的值传递进来,不会影响外部a的值。
比如,我将a,b的值传入表达式,然后返回a+b,因为是值传递,所以返回的直接是10+20,而不是a+b本身。所以,即使我后来更改了a和b的值,对结果依然不会有影响
int a = 10;
int b = 20;
auto Lambda = [a,b]()->int {
return a + b;
};
a = 20;
b = 30;
cout << Lambda() << endl; //30
外部变量捕获 [capture list]
重点记录一下外部捕获变量的规则
值捕获
表达式默认的捕获是值捕获,即只捕获变量的值,不会改变其本身
int a = 10;
int b = 20;
auto Lambda = [a,b]{
cout << a << endl;
cout << b << endl;
};
a = 20;
b = 30;
Lambda();//10,20
引用捕获
当我引用捕获a时,在调用表达式之前,改变a,表达式里面的a也会改变
int a = 10;
int b = 20;
auto Lambda = [&a,b]{
cout << a << endl;
cout << b << endl;
};
a = 20;
b = 30;
Lambda();//20,20
隐式捕获(默认全部值捕获)
只需在捕获列表里传入‘=’,就会默认全部都是值捕获(表达式内部用到的值)
int a = 10;
int b = 20;
int c = 30;
auto Lambda = [=]{
cout << a << endl;
cout << b << endl;
};
a = 20;
b = 30;
Lambda();//10,20
隐式捕获(默认全部引用捕获)
默认,表达式内部的变量全部是外部变量的引用,因此,外部更改了变量,里面也会更改。
int a = 10;
int b = 20;
auto Lambda = [&]{
cout << a << endl;
cout << b << endl;
};
a = 20;
b = 30;
Lambda();//20,30
指定某一个变量是值捕获,其余全是引用捕获
除了a之外的所有出现在表达式内部的变量,都是引用捕获。
int a = 10;
int b = 20;
auto Lambda = [&,a]{
cout << a << endl;
cout << b << endl;
};
a = 20;
b = 30;
Lambda();//10,30
指定某一个变量是引用捕获,其余全是值捕获
与上面的同理
int a = 10;
int b = 20;
auto Lambda = [=,&a]{
cout << a << endl;
cout << b << endl;
};
a = 20;
b = 30;
Lambda();//20,20