lundi 20 mai 2019

How does C++ store variables captured by a lambda that have gone out of scope?

If a function returns a lambda that captures and mutates a value declared in the scope of the function, where/how is that value stored in memory so the lambda may safely use it?

This example is from listing 6.7 in 'Functional Programming in C++' by Ivan Čukić. It's a utility memoization method that caches results for fast lookup later. The contrived usage computes and then retrieves a cached Fibonacci number:

#include <iostream>
#include <map>
#include <tuple>

template <typename Result, typename... Args>
auto make_memoized(Result (*f)(Args...)) {
    std::map<std::tuple<Args...>, Result> cache;

    return [f, cache](Args... args) mutable -> Result {
        const auto args_tuple = std::make_tuple(args...);
        const auto cached = cache.find(args_tuple);

        if (cached == cache.end()) {
            auto result = f(args...);
            cache[args_tuple] = result;
            return result;
        } else {
            return cached->second;
        }
    };
}

unsigned int fib(unsigned int n) {
    return n < 2 ? n : fib(n - 1) + fib(n - 2);
}

int main() {
    auto fibmemo = make_memoized(fib);
    std::cout << "fib(15) = " << fibmemo(15) << '\n';
    std::cout << "fib(15) = " << fibmemo(15) << '\n';
}

My expectation was that cache would be destroyed when make_memoized returned, so a retrospective call to the lambda would have referred to a value that has gone out of scope. However it works fine (g++ 9.1 on OSX).

I can't find a concrete example of this sort of usage on cppreference.com. Any help leading me to the right terminology to search for is greatly appreciated.

Aucun commentaire:

Enregistrer un commentaire