这个C++ 11代码(memoize)做了什么?

Mir*_*pas 15 c++ lambda memoization c++11

我发现了一篇包含此代码的文章:

template <typename ReturnType, typename... Args>
std::function<ReturnType (Args...)>
memoize(std::function<ReturnType (Args...)> func)
{
    std::map<std::tuple<Args...>, ReturnType> cache;
    return ([=](Args... args) mutable {
            std::tuple<Args...> t(args...);
            if (cache.find(t) == cache.end())                
                cache[t] = func(args...);
            return cache[t];
    });
}
Run Code Online (Sandbox Code Playgroud)

你能解释一下吗?我在这里无法理解很多东西,但最奇怪的是缓存是本地的而不是静态的,但也许我错了......

And*_*ron 25

这是简单的C++ 1x memoization实现.

memoize函数返回一个闭包.返回值是一个函数,其状态不是通过参数传递的状态(在本例中为cache变量).

[=]匿名函数中的位表示返回的函数应该获取所有局部变量的副本.该cache变量不是静态的,因为它意味着在返回函数的调用之间共享.

因此,每次调用memoize都会返回一个与它自己不同的函数cache.返回的特定闭包的后续调用memoize将从闭包中插入/获取值cache.

您可以将此视为与更老式的OOP版本相当:

template <typename ReturnType, typename... Args>
class Memoize
{
    std::map<std::tuple<Args...>, ReturnType> cache;
public:
    ReturnType operator() (Args... args)
    {
        std::tuple<Args...> t(args...);
        if (cache.find(t) == cache.end())                
            cache[t] = func(args...);
        return cache[t];
    }
};
Run Code Online (Sandbox Code Playgroud)

  • @Nordlöw:问题中使用的风格是我所知道的所有编程语言中有状态闭包的常用习惯.坚持众所周知的用法是一件好事(tm).要使闭包线程安全,可以使用reader-write锁(`boost :: shared_mutex`),它可以在与缓存相同的范围内声明.在lambda中根据需要锁定地图. (2认同)

Mat*_* M. 9

缓存嵌入到lambda本身,并且是本地的.

因此,如果您创建两个lambdas,每个lambda都将拥有自己的缓存.

这是实现简单缓存的好方法,因为一旦lambda超出范围,就会清除所使用的内存,并且你没有内存爆炸.