This is because the scope of the filters vector survives one of the functions. When the function exits, the filters vector still exists, and the captured divisor reference now hangs.
For what I understand, filter.emplace_back is returned only after the lambda expression is complete and during its execution the divisor is valid.
This is not true. The vector stores the lambda created from the closure and does not perform the lambda, you execute the lambda after the function exits. Technically, a lambda is built from a closure (a compiler dependent class) that uses an internal reference, e.g.
#include <vector> #include <functional> struct _AnonymousClosure { int& _divisor; // this is what the lambda captures bool operator()(int value) { return value % _divisor == 0; } }; int main() { std::vector<std::function<bool(int)>> filters; // local scope { int divisor = 42; filters.emplace_back(_AnonymousClosure{divisor}); } // UB here when using filters, as the reference to divisor dangle }
source share