lambda 隐式捕获与this捕获

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隐式捕获,20后不支持了,但下面显式捕获编译会有告警
        auto lambda = [=,this] ()	//捕获this的形式是值捕获,但this是指针,本质也是引用捕获
        {
            this->x++;	//会修改到捕获的变量
            this->y++;
            cout<<data<<endl;  //data的生命周期是invoke内的,x,y生命周期是point
        };
		
		/* 隐式捕获
        auto lambda = [=] ()	//捕获this的形式是值捕获,但this是指针,本质也是引用捕获
        {
            x++;	//会修改到捕获的变量
            y++;
            cout<<data<<endl;  //data的生命周期是invoke内的,x,y生命周期是point
        };*/
        return lambda;
    }
};


int main()
{
	Point p1{100,200};
    auto lambda=p1.invoke();// 本质调用形式是invoke(&p1);

    lambda();
    cout<<sizeof(lambda)<<endl;	//大小16,point* 8byte,int 4byte
    p1.print();
	
}

代码分析

//本质上,lamba的替代形式如下:
 struct lambda{	//this捕获的替代形式
     Point* this;	//变量指针
     int data;	//int 4byte  对齐后16byte

     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已经析构
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

技术的微光

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值