lambda 隐式捕获与this捕获
lambda可以类中捕获当前类实例的this指针,捕获方式表明是值捕获:
auto lambda = [=,this]
但this是指针,本质也是引用捕获,修改this成员会影响实例的数据。
此外,在类中捕获的变量,要分清楚各自的生存周期,如果周期不一致,如果this里面的周期和类接口中的变量,
生存周期不一致,可能导致后续使用的隐蔽错误
实例代码-1
#include <iostream>
#include <vector>
using namespace std;
class Point{
public:
double x;
double y;
void print() const{
std::cout << x<< ", "<<y<<endl;;
}
auto invoke()
{
int data=100;
auto lambda = [=,this] ()
{
this->x++;
this->y++;
cout<<data<<endl;
};
return lambda;
}
};
int main()
{
Point p1{100,200};
auto lambda=p1.invoke();
lambda();
cout<<sizeof(lambda)<<endl;
p1.print();
}
代码分析
struct lambda{
Point* this;
int data;
void operator ()(){
this->x++;
this->y++;
cout<<data;
};
};
编译及运行结果分析
kongcb@tcu-pc:~/testcode/lambda$ g++ lambda_capture_this1.cpp -o lambda_capture_this1
lambda_capture_this1.cpp: 在成员函数‘auto Point::invoke()’中:
lambda_capture_this1.cpp:35:26: 警告:explicit by-copy capture of ‘this’ redundant with by-copy capture default
35 | auto lambda = [=,this] () //捕获this的形式是值捕获,但this是指针,本质也是引用捕获
| ^~~~
kongcb@tcu-pc:~/testcode/lambda$ ./lambda_capture_this1
100
16
101, 201 //因为本质还是引用捕获,所有还是会修改值
//如果不想看到警告,直接将auto lambda = [=,this] () 替换为:auto lambda = [=] ()
kongcb@tcu-pc:~/testcode/lambda$ g++ lambda_capture_this1.cpp -o lambda_capture_this1
kongcb@tcu-pc:~/testcode/lambda$ ./lambda_capture_this1
100
16
101, 201
kongcb@tcu-pc:~/testcode/lambda$
隐蔽错误
//错误示范,如上,比较常见且不易查看,如上的class Point 保持一样,将main部分替换如下
auto process()
{
Point p1{100,200};
auto lambda=p1.invoke();// 本质调用形式是invoke(&p1);
lambda();
cout<<sizeof(lambda)<<endl;
p1.print();
return lambda; //return后lambda中捕获的p1实际析构了
}
int main()
{
auto lam = process(); //lam获得的lamba捕获的p1析构了
lam();
}
//编译及结果
kongcb@tcu-pc:~/testcode/lambda$ g++ lambda_capture_this1.cpp -o lambda_capture_this1
kongcb@tcu-pc:~/testcode/lambda$ ./lambda_capture_this1
100
16
101, 201
段错误 (核心已转储) //内存point已经析构