C ++ lambda 'this'-invalidator after move operation

I have the following (simplified) code in my current project:

#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; } 

When I run it, instead of the expected value, the value 50 will be printed. I assume that this is because the lambda function captures the current this pointer. After the move operation, the this pointer changes, and the function writes the incorrect a .

Now my question is: Is there a way to change the linked lambda link to the new Test to print the value 2?

+8
c ++ lambda move
source share
1 answer

The solution is not to capture this at all. Instead, change your captured function type to accept it. And use a pointer to the element (fixed by value) for indirect access to a .

 std::function<void(Test*)> lambda; void setFunction(){ auto a = &Test::a; lambda = [=](Test *t){ (t->*a) = 2; }; } int callAndReturn(){ lambda(this); return a; } 

Living example


As Galik noted, if you only need to access one hard-coded element, then you do not even need this pointer to a member. So lambda can be without capture:

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

All Articles