2

コンテナから自分自身を削除する可能性のあるコールバックを登録したいと考えています。しかし、キャプチャされた変数がクリーンアップされているように見えることがわかりました。次のようなコード:

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 オブジェクトをラムダに移動して、その破棄を遅らせます。

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;
}
4

1 に答える 1

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;
}
于 2013-06-27T15:30:31.353 に答える