如果我在lambda中删除包含该lambda的对象,究竟会发生什么?

时间:2017-03-10 11:51:25

标签: c++ c++11 lambda

我有一个回调系统,可以在发生事件时保存lambda。要获得通知,您必须将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无效)。你能解释一下这些情况下究竟发生了什么吗?

你将如何处理回调的情况?在调用回调之前制作副本(似乎是禁止的)?

1 个答案:

答案 0 :(得分:5)

考虑发生了什么:您在<{1}}内存储了使用 lambda表达式生成的函数对象

std::function<void()>现在拥有生成的功能对象。它也位于std::function内。

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

来自std::function上的std::map::clear文档:

  

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

可以安全地假设cppreference.org clear使存储在其中的数据无效。因此,使用存储在生成的函数对象中的数据是不安全的,可能会导致未定义的行为

这是粗略简化你正在做的事情:

std::map