C ++: не может захватить этот контекст 2 раза в лямбдах - PullRequest
0 голосов
/ 12 марта 2020

Ниже приведен минимальный код для воспроизведения проблемы:

std::vector<std::function<bool()>> injections;
struct Obj {
    void load() {
        injections.push_back([&] {
            std::cout << ++counter << std::endl;
            injections.push_back([&] {
                std::cout << ++counter << std::endl;
                return true;
            });
            // std::cout << ++counter << std::endl;
            return true;
        });
    }
    int counter = 0;
};
int main() {
    Obj obj;
    obj.load();
    while(true)
        for(auto i = 0; i < injections.size(); i++) {
            auto pop = injections[i]();
            if(pop)
                injections.erase(injections.begin() + i--);
        }
}

При выполнении именно так все работает правильно, но без комментария закомментированной строки происходит сбой. Проблема в том, что после нажатия второй лямбды this указывает на какую-то фигню, а ++counter выбрасывает. Я ожидаю, что первая лямбда будет захвачена по ссылке на членов, которые не выйдут за пределы go после окончания load(), что именно и происходит. Для второй лямбды я собираюсь ссылаться на ссылки, делая доступным counter, что опять же происходит с использованием плохой закомментированной строки. Похоже, что конструкция лямбда делает недействительным все после нее. В чем причина этого и некоторых решений?

1 Ответ

2 голосов
/ 12 марта 2020

Когда вы вставляете что-то в injections, предыдущий std::function<bool()> может быть перемещен (и уничтожен).

Поэтому код после injections.push_back больше не должен использовать захваты / члены.

В основном это эквивалентно использованию delete this; в методе.

...