在执行时删除 lambda 是否有效?

Is it valid to delete a lambda while executing it?

是否允许在执行关联的 lambda 函数时删除 lambda 对象,只要注意在删除后不访问任何捕获的状态即可?

考虑以下示例:

int main() {
    int x = 1;

    std::function<void()> d;

    auto l = new auto([x, &d]() { 
        fmt::print("x is {}\n", x);
        d();
        fmt::print("I'm deleted\n");
    });

    d = [l](){ delete l; };

    (*l)();
}

在这里,l 指向的 lambda 通过 d 函数 1 使用类似 Rube Goldberg 的方法删除自身。删除后,它会打印一条不访问任何捕获状态的固定消息。

它是定义的行为吗?


1 我想不出更好的方法来打破 lambda 代码之间的循环依赖,它需要看到指向自身的东西:我愿意接受更好的方法选项。

标准中可能没有明确的规范。

虽然没有具体说明,但 lambda 类型“本质上”类似于特殊 类。继续这个类比,问题将与“delete this; 的定义是否明确”相同。该问题的 typical answer 是:

As long as you’re careful, it’s okay (not evil) for an object to commit suicide (delete this).

Here’s how I define “careful”:

  1. You must be absolutely 100% positively sure that this object was allocated via new (not by new[], nor by placement new, nor a local object on the stack, nor a namespace-scope / global, nor a member of another object; but by plain ordinary new).
  2. You must be absolutely 100% positively sure that your member function will be the last member function invoked on this object.
  3. You must be absolutely 100% positively sure that the rest of your member function (after the delete this line) doesn’t touch any piece of this object (including calling any other member functions or touching any data members). This includes code that will run in destructors for any objects allocated on the stack that are still alive.
  4. You must be absolutely 100% positively sure that no one even touches the this pointer itself after the delete this line. In other words, you must not examine it, compare it with another pointer, compare it with nullptr, print it, cast it, do anything with it.

要将这些点转换为 lambda,“调用成员函数”变为“调用 lambda”,“任何数据成员”变为“任何捕获”。您的示例满足所有要点。