本质是函数
完整结构:
[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
重点记录一下外部捕获变量的规则
表达式默认的捕获是值捕获,即只捕获变量的值,不会改变其本身
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