【问题标题】:Remove self from the container in the lambda从 lambda 中的容器中删除 self
【发布时间】:2013-06-27 15:21:17
【问题描述】:

我想注册一个回调,它可以将自己从其容器中移除。但是我发现捕获的变量似乎被清理了。代码如下:

class A {
    int val_;
public:
    A(int val) : val_(val) {}
    void foo() {
        std::cout << val_ << std::endl;
    }
};

int main()
{
    const int func_index = 1;
    std::unordered_map<int, std::function<void(void)>> container;
    A a(10);
    container.insert(std::make_pair(func_index, [&container, func_index, &a] () {
        container.erase(func_index);
        for (int i = 0; i < 10; i++) {
            a.foo();
        }
    }));
    container[func_index]();
    return 0;
}

解决方案,将 std::function 对象移入 lambda 以延迟其销毁:

class A {
    int val_;
public:
    A(int val) : val_(val) {}
    void foo() {
        std::cout << val_ << std::endl;
    }
};

int main()
{
    const int func_index = 1;
    std::unordered_map<int, std::function<void(void)>> container;
    A a(10);
    container.insert(std::make_pair(func_index, [&container, func_index, &a] () {
        std::function<void(void)> self = std::move(container[func_index]);
        container.erase(func_index);
        for (int i = 0; i < 10; i++) {
            a.foo();
        }
    }));
    container[func_index]();
    return 0;
}

【问题讨论】:

  • 您可能需要在此处添加更多详细信息,说明实际未按预期工作的内容。
  • “我发现捕获的变量似乎已被清理”是什么意思?

标签: c++ c++11 lambda


【解决方案1】:

您的代码具有未定义的行为,因为您在从容器中删除闭包后访问闭包。您应该在 使用它之后从容器中移除闭包:

class A {
    int val_;
public:
    A(int val) : val_(val) {}
    void foo() {
        std::cout << val_ << std::endl;
    }
};

int main()
{
    const int func_index = 1;
    std::unordered_map<int, std::function<void(void)>> container;
    A a(10);
    container.insert(std::make_pair(func_index, [&container, func_index, &a] () {
        for (int i = 0; i < 10; i++) {
            a.foo();
        }
        container.erase(func_index);
    }));
    container[func_index]();
    return 0;
}

【讨论】:

  • 谢谢!但我必须把erase 放在lambda 的开头。有什么方法可以禁用从容器中索引此函数,直到我可以在 lambda 末尾实际删除它?
  • @user2134183:在调用erase 之前,您始终可以将相关数据保存到局部变量中。重要的是在擦除闭包后访问捕获的变量。
  • 谢谢!我找到了另一种解决方法!我将容器中的 std::function 对象移动到 lambda 中,并从容器中删除了空对象。只需在 lambda 的开头添加std::function&lt;void(void)&gt; self = std::move(container[func_index]);
猜你喜欢
  • 1970-01-01
  • 2012-07-12
  • 1970-01-01
  • 2021-05-28
  • 2011-05-27
  • 1970-01-01
  • 2016-12-23
  • 1970-01-01
  • 2016-01-19
相关资源
最近更新 更多