c++ - 可以在 lambda 运行之前使 lambda 捕获的 [this] 指针无效吗?
问题描述
假设我们有一个带有一些对象的 STL 容器,这些对象可以将函数发布到队列中以便稍后执行。但是在这些函数被执行之前,容器被修改为指向该对象的指针无效。让我用一个例子来说明:
#include <vector>
#include <functional>
class Class_A
{
public:
std::function<void()> getFunctionToRunLater()
{
return [this] () { somethingToDo(); moreThingsToDo(); };
// Returns a lambda function that captures the this pointer,
// so it can access the object's methods and variables.
}
void somethingToDo();
void moreThingsToDo();
}
int main()
{
std::vector<Class_A> vec;
vec.push_back(Class_A());
std::function<void()> pendingFunction = vec.back().getFunctionToRunLater();
// More code...
pendingFunction();
}
一切都很好,对吧?我们得到一个对象想要运行的函数,经过一些逻辑,我们执行该函数。这表示将函数发布到队列,并且它们执行队列中的所有函数。但现在看看这个:
int main()
{
std::vector<Class_A> vec;
vec.push_back(Class_A());
std::function<void()> pendingFunction = vec.back().getFunctionToRunLater();
// More code...
vec.reserve(1000);
// This will surely reallocate the vector, invalidating all pointers.
pendingFunction();
// And now my program is going straight down to hell, right?
}
我的假设正确吗?如果 lambda 根本没有捕获任何东西会发生什么,程序仍然会在逻辑上被破坏吗?如果 lambda 没有捕获 this 指针,而是专门捕获其他一些类字段怎么办?
解决方案
现有答案已经提到可以使指针失效。如前所述,避免该问题的一种方法是更改*this
by或副本shared_ptr
的所有权。unique_ptr
然而,这需要额外的成本(动态分配或额外复制),有时根本不可能(不可复制的类型)。
相反,我会建议一种首先不会导致此问题的设计,即不使this
指针成为 lambda 状态的一部分。将对象作为参数:
std::function<void(Class_A&)> getFunctionToRunLater()
{
return [] (Class_A& obj) { obj.somethingToDo(); obj.moreThingsToDo(); };
}
推荐阅读
- c# - EWS 在 C# 中发送邮件失败,但在 VB.Net 中没有
- javascript - 如何在文档完全加载 QWebEngineView 之前运行 JavaScript 代码?
- microsoft-graph-api - 设置 MS 图形日历订阅返回“访问 OData 已禁用”
- cryptocurrency - 加密货币交易所如何从交易中分一杯羹?
- groovy - 通过管道 groovy 运行 XVFB
- java - 在 docker run 的入口点中使用 cp
- .net - 如何在打开对话框的表单窗口顶部打开 VB.Net 对话框窗口?
- r - 指示 RMarkdown 使用相对文件路径或停止缩短文件夹名称
- firebase - Firebase 获取基于角色的文档
- reactjs - 用于生成布局的 Gatsby 动态路由 URL