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

Ove*_*ade 10 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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

Sto*_*ica 6

解决方案是根本不捕获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;
}
Run Code Online (Sandbox Code Playgroud)

Live Example


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

void setFunction(){
   lambda = [](Test *t){
       t->a = 2;
   };
}  
Run Code Online (Sandbox Code Playgroud)

  • 你不能只做`t-&gt;a = 2;`而忘记成员指针吗? (2认同)