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

C++ lambda ´this´ pointer invalidation after move operation

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

#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?

解决办法是完全不捕获 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;
   };
}