Как в C ++ хранятся переменные, захваченные лямбда-выражениями, которые вышли из области видимости? - PullRequest
1 голос
/ 21 мая 2019

Если функция возвращает лямбду, которая захватывает и изменяет значение, объявленное в области действия функции, где / как это значение хранится в памяти, чтобы лямбда могла безопасно его использовать?

Этот пример изперечисление 6.7 в «Функциональное программирование на C ++» Ивана Чукича.Это служебный метод запоминания, который кеширует результаты для быстрого поиска позже.Придуманное использование вычисляет, а затем извлекает кэшированное число Фибоначчи:

#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';
}

Я ожидал, что cache будет уничтожено при возврате make_memoized, поэтому при ретроспективном вызове лямбды будет указано значениеэто вышло за рамки.Однако он работает нормально (g ++ 9.1 на OSX).

Я не могу найти конкретный пример такого рода использования на cppreference.com.Любая помощь, ведущая меня к правильной терминологии для поиска, очень ценится.

1 Ответ

2 голосов
/ 21 мая 2019

[f, cache] захватывает переменные по значению.После захвата по значению, срок жизни захваченного VAR должен быть таким же, как сама лямбдасвязаны между собой.Таким образом, хотя код все еще компилируется, использование возвращаемой лямбды больше не безопасно, поскольку cache к тому времени уже уничтожено.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...