如果我在lambda中删除容纳lambda的对象,那会发生什么

What exactly happens if I delete inside a lambda the object that holds that lambda?

本文关键字:lambda 对象 什么 删除 如果      更新时间:2023-10-16

我有一个回调系统,该回调系统在发生某些事情时会发出lambdas。要获得通知,必须将lambda注册到标识符,或者如果您不想再次通知,请取消注册。

我遇到的问题是,我已经注册了lambdas,将在该系统中取消注册,从而导致当前执行的lambda的破坏。而且我认为这不是安全的。但我不确定。

例如:

#include <map>
#include <functional>
#include <iostream>

int main() {
  std::map<int, std::function<void ()>> m;
  m[10] = [&m] () {
    int i = m.size();  // Just cheking the internal state of the lambda
    m.clear();
    //i += m.size();   // If I uncomment this the std::cout is not working.
    std::cout<< "What happens? " << i << std::endl;
  };
  m[10]();
  return 0;
}

我看到的是,当我在m.clear()之后检查Lambda的状态时,我会感到奇怪的行为(例如std::cout不起作用)。您能解释一下在这些情况下到底会发生什么?

您将如何通过回调处理这些情况?在调用回调之前制作副本(似乎是不可以)?

考虑正在发生的事情:您正在存储用 std::function<void()>中的 lambda expression生成的函数对象

std::function现在拥有生成的函数对象。它也位于std::map中。

然后,您通过参考捕获相同的std::map 并在其上调用std::map::clear,删除存储的std::function

来自cppreference.org上的std::map::clear文档:

从容器中删除所有元素。 使参考包含元素的任何参考,指针或迭代器无效。任何过去的迭代器仍然有效。

可以肯定地假设clear std::map无效存储在其中的数据。因此,使用存储在生成的函数对象中的数据不安全,并且可能导致未定义的行为


这是A 粗糙简化您在做什么:

using func = std::function<void()>;
func f;
f = [&f]{ int a = 0; f.~func(); std::cout << a; };