3

是否有用于“缓存计算”/“缓存 getter”的通用模式或现成的 boost 类?

我的意思是这样的:

class Test{
public:
     Value getValue() const;
protected:
     Value calculateValue() const;//REALLY expensive operation.
     mutable bool valueIsDirty;
     mutable Value cachedValue;
}

Value Test::getValue() const{
     if (valueIsDirty){
         cachedValue = calculateValue();
         valueIsDirty = false;
     }
     return cachedValue;
}

我可以使用std::pair<Value, bool>并变成宏,但是如果值依赖于其他值(存储在其他类中)并且这些值也可以被缓存getValue/calculateValue,这并没有真正的帮助。

这种“模式”有现成的解决方案吗?目前我手动处理这些缓存值,但这不是“漂亮”。

限制:
c++03 标准。允许升压。

4

2 回答 2

1

代理设计模式可以帮助解决这个问题。

一个典型的实现将定义一个ValuePtr行为就像一个普通的类Value*,即它有一个重载的operator->and operator*。但这些运算符不是直接访问底层Value对象,而是包含决定加载或重新计算实际值的逻辑。这种额外的间接级别将封装代理逻辑。

如果您需要计算对其他对象的引用,也许std::shared_ptr<Value>可以用作内部的底层数据类型ValuePtr

有关代码示例,请参见此站点Boost.Flyweight也可能有所帮助。

于 2013-07-18T11:55:02.660 回答
1

这就是我最终使用的:

template<typename T, typename Owner> class CachedMemberValue{
public:
    typedef T (Owner::*Callback)() const;
    T get(){
        if (dirty){
            cachedValue = (owner->*calculateCallback)();
            dirty = false;
        }
        return cachedValue;
    }
    const T& getRef(){
        if (dirty){
            cachedValue = (owner->*calculateCallback)();
            dirty = false;
        }
        return cachedValue;
    }
    void markDirty(){
        dirty = true;
    }
    CachedMemberValue(Owner* owner_, Callback calculateCallback_)
        :owner(owner_), calculateCallback(calculateCallback_), dirty(true){
    }
protected:
    Owner *owner;
    Callback calculateCallback;
    bool dirty;
    T cachedValue;
private:
    CachedMemberValue(const CachedMemberValue<T, Owner>&){
    }
    CachedMemberValue<T, Owner>& operator=(const CachedMemberValue<T, Owner>&){
        return *this;
    }
};

用法:

class MyClass{
    public:
        int getMin() const{
            return cachedMin.get();
                }
            void modifyValue() { /*... calculation/modification*/ cachedMin.markDirty();}
        MyClass(): cachedMin(this, &MyClass::noncachedGetMin){}
    private:
        int noncachedGetMin() const{ /*expensive operation here*/ ... }
        mutable CachedMemberValue<int, MyClass> cachedMin;
};
于 2013-07-31T18:23:48.063 回答