移动操作后 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;
}
正如 Galik 指出的那样,如果您只需要访问一个硬编码成员,那么您甚至不需要该成员指针。因此 lambda 可以是无捕获的:
void setFunction(){
lambda = [](Test *t){
t->a = 2;
};
}
我当前的项目中有以下(简化的)代码:
#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;
}
正如 Galik 指出的那样,如果您只需要访问一个硬编码成员,那么您甚至不需要该成员指针。因此 lambda 可以是无捕获的:
void setFunction(){
lambda = [](Test *t){
t->a = 2;
};
}