Lambda表达偷偷地抓住了“这个”

时间:2013-03-25 04:38:33

标签: c++ c++11 lambda

假设我有以下内容。

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. 崩溃尝试取消引用nullptrf1, f2, f3, f4)。
  4. 我理解这是因为有些人在this的成员函数中隐式或明确地捕获“A”。

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

    我花了一段时间处理由f1类似的错误导致的错误,认为它会捕获x并且从不认为它会捕获this,所以我认为它会记录下来是有用的。

1 个答案:

答案 0 :(得分:8)

没有正式规则可以确定此行为。因为此行为是未定义

你的lambda正在访问一个不存在的对象。您无法直接按值捕获成员变量;你总是通过this捕获它们。这意味着您通过引用捕获它们。删除对象后,任何访问该已删除对象的尝试都会导致未定义的行为。

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