从lambda中的容器中移除self

Qin*_*Yun 2 c++ lambda c++11

我想注册一个可能从容器中删除自己的回调.但我发现捕获的变量似乎被清除了.像这样的代码:

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;
}
Run Code Online (Sandbox Code Playgroud)

解决方案,将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;
}
Run Code Online (Sandbox Code Playgroud)

Man*_*rse 5

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

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;
}
Run Code Online (Sandbox Code Playgroud)