移动操作后C ++ lambda'this'指针失效

时间:2017-06-25 10:04:50

标签: c++ lambda move

我目前的项目中有以下(简化)代码:

#include <iostream>
#include <string>
#include <functional>
#include <vector>


class Test{

public:

    Test() = default;
    Test(const Test& other) = delete;
    Test& operator=(const Test& other) = delete;
    Test(Test&& other) = default;
    Test& operator=(Test&& other) = default;



    void setFunction(){
       lambda = [this](){
           a = 2;
       };
    }  

    int callAndReturn(){
       lambda();
       return a;
    }

private:
    std::function<void()> lambda; 
    int a = 50;
};


int main()
{
  Test t;
  t.setFunction();
  std::vector<Test> elements;
  elements.push_back(std::move(t));
  std::cout << elements[0].callAndReturn() << std::endl;
}

当我运行它时,打印值50而不是预期值2.我想这是因为lambda函数捕获当前的this指针。移动操作后,this指针发生变化,函数写入错误的a

现在我的问题是:有没有办法将lambda捕获的引用更改为新Test,以便打印值2?

1 个答案:

答案 0 :(得分:4)

解决方案根本不是捕获this。而是,更改捕获的函数类型以接受它。并使用指向成员的指针(由值捕获)来间接访问a

std::function<void(Test*)> lambda; 

void setFunction(){
   auto a = &Test::a;
   lambda = [=](Test *t){
       (t->*a) = 2;
   };
}  

int callAndReturn(){
   lambda(this);
   return a;
}

Live Example

正如Galik所说,如果你只需要访问一个硬编码成员,那么你甚至不需要指向成员的指针。因此lambda可以是无捕获的:

void setFunction(){
   lambda = [](Test *t){
       t->a = 2;
   };
}