Lambda表达式偷偷地捕获了' this '

Lambda expression sneakily capturing `this`

本文关键字:this 表达式 Lambda      更新时间:2023-10-16

假设我有以下内容:

struct A
{
    int x;
    std::function<int()> f1() { return [=](){ return x; }; }
    std::function<int()> f2() { return [=](){ return this->x; }; }
    std::function<int()> f3() { return [this](){ return x; }; }
    std::function<int()> f4() { return [this](){ return this->x; }; }
    std::function<int()> f5()
    {
        int temp = x;
        return [=](){ return temp; };
    }
}

现在我有了下面的代码:

auto a = std::make_shared<A>();
a->x = 5;
std::function<int()> f = a.f#();
a.reset();
int x = f();

其中f#指向f1, f2, f3, f4, f5中的任意一个。

这些函数表现出以下两种行为之一:

  1. 在调用(f5)或
  2. 时返回5
  3. 试图解引用nullptr (f1, f2, f3, f4)时崩溃。

我理解这是因为有些人在A的成员函数中隐式或显式地捕获了"this"。

决定行为1或行为2的正式规则是什么?

我花了一段时间处理一个由类似f1的东西引起的bug,认为它会捕获x,从未考虑它会捕获this,所以我认为把这个记录下来会很有用。

没有正式的规则来决定这种行为。因为此行为未定义

你的lambda正在访问一个不存在的对象。不能直接按值捕获成员变量;你总是通过this来捕捉它们。也就是说你是通过引用来捕捉它们的。一旦对象被删除,任何访问该对象的尝试都会导致未定义的行为。

例外是f5,它应该返回一个一致的值,保证。它与原始对象完全断开。