我在当前项目中有以下(简化)代码:
#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?
解决方案是根本不捕获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)
正如 Galik 指出的那样,如果您只需要访问单个硬编码成员,那么您甚至不需要指向成员的指针。因此 lambda 可以是无捕获的:
void setFunction(){
lambda = [](Test *t){
t->a = 2;
};
}
Run Code Online (Sandbox Code Playgroud)