等价于匿名函数对象,又称为“闭包”(closure),更便捷,表达更直接。表达式要素包括:
1:捕获列表
2:参数列表
3:mutable修饰符,表达传值或传引用
4:noexcept
5:返回值类型声明 ->
6:表达式体{...}
lambda表达式可接受参数,可返回值,可模板化,也可以通过传值或传引用从闭包范围内访问变量。
编译器将lambda表达式编译为具名函数对象
对于捕获列表:
lambda表达式,从闭包作用域捕获变量而获得状态,分为传值和传引用。
捕获变量登记与函数对象中的示例数据成员。
[=] 值捕获所有变量
[&] 引用捕获所有变量
[&x] 引用捕获x变量
[x] 值捕获x
[=,&x] 默认值捕获,x变量通过引用捕获
[&,x] 默认引用捕获,x通过值捕获
[this] 捕获当前对象,可访问所有共有成员,C++20中不允许隐式捕获this
[=,x],[&,&x] 错误,重复指定
注意:即便默认要值捕获,全局变量总是使用引用捕获
使用初始化捕获表达式表达move捕获
示例:
#include <iostream>
#include <vector>
using namespace std;
class Point{
public:
double x;
double y;
void print() const {
std::cout << x<< ", "<<y<<endl;;
}
};
int number=100; //全局变量可以在lambda修改,跨越所有,捕获类型管理不到
int main()
{
Point p1{100,200};
Point p2{100,200};
//=表示值捕获,就是将外部变量拷贝进来,声明的时候,只能用auto,因为是匿名对象
//如果没有mutable,会报错,不允许修改p1,p2;如果修改捕获对象,就需要mutable
auto lambda1 = [=] (int n) mutable //p1,p2为外部变量,实际调用了拷贝构造函数
{
p1.x+=n; //从外部拷贝进来了,此处修改不影响外部p1
p1.y+=n;
p2.x+=n;
p2.y+=n;
p1.print(); //print()有个const,如果此时p1,p2没修改(即上面4行不存在),如果print没有const,lambda也需要mutable(编译器认为调用函数也可能更改了)
p2.print();
number++; //全局变量直接使用
};
//Lambda_Value lambda1(p1,p2);
lambda1(10); //外部看不到p1,p2,打印110,210
lambda1(10); //多执行一次,会改变lambda对象内部的p1,p2,栈上的lambda对象没有销毁,120,220
p1.print(); //不改变外部的p1,p2,所以此处打印是一样的,100,200
p2.print();
cout<<sizeof(lambda1)<<endl; //没有捕获,就是一个空类,有捕获后,就有32byte
cout<<sizeof(Point)<<endl; //
cout<<"lambda1------------"<<endl;
auto lambda2 = [&] (int n) //引用捕获,不用mutable,lambda内部修改会传递到外部
{
p1.print();
p2.print();
p1.x+=n;
p1.y+=n;
p2.x+=n;
p2.y+=n;
number++; //全局的执行也有效果
};
//Lambda_Ref lambda2(p1,p2);
lambda2(100);//p1,p2先打印原始值,之后 p1:200,300; p2:200,300
p1.print(); //200,300
p2.print();
p1.x+=5; //p1.x = 205
p1.y+=5; //p1.y = 305
p2.x+=5;
p2.y+=5;
lambda2(100); //引用捕获,外部更改也会影响引用捕获内部变量,先打印205,305,之后305,405
//return lambda2; //隐蔽错误,因为lambda2是引用捕获,函数返回后,p1,p2销毁了,值捕获就没有问题
cout<<number<<endl; //lambda内部修改此处表现出来了
cout<<sizeof(lambda2)<<endl;//只是引用,大小不计算引用参数大小
cout<<"lambda2------------"<<endl;
auto lambda3 = [=, &p1] () //默认值捕获,但p1使用引用捕获
{
p1.x++;
p1.y++; //p1修改外部更改,306,406
p2.print(); //值捕获305,405
};
lambda3();
//auto lambda4 = [ &, &p1] () 或者 auto lambda4 = [ =, p1] () 都是重复性错误
auto lambda4 = [ &, p1] () //默认引用捕获,p1是值捕获
{
p1.print();
p2.x++; //引用捕获,p2:306,406
p2.y++;
};
lambda4();
// auto lambda5 = [p2, &number] () //失败,number不能
auto lambda5 = [p2] () //单独对p2值捕获
{
p2.print(); //306,406
};
lambda5();
auto lambda6 = [&p1] () //单独对p1引用捕获
{
p1.x++;
p1.y++;
};
lambda6();
}
标签:闭包,变量,捕获,知识,引用,表达式,lambda From: https://www.cnblogs.com/52ld/p/17285415.html