首页 > 解决方案 > 可以在 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 指针,而是专门捕获其他一些类字段怎么办?

标签: c++lambdathis

解决方案


现有答案已经提到可以使指针失效。如前所述,避免该问题的一种方法是更改*this​​ by或副本shared_ptr的所有权。unique_ptr然而,这需要额外的成本(动态分配或额外复制),有时根本不可能(不可复制的类型)。

相反,我会建议一种首先不会导致此问题的设计,即不使this指针成为 lambda 状态的一部分。将对象作为参数:

std::function<void(Class_A&)> getFunctionToRunLater()
{
    return [] (Class_A& obj) { obj.somethingToDo(); obj.moreThingsToDo(); };
}

推荐阅读