“缓存计算”/“缓存的getter”是否有通用模式或即用型升级类?
我的意思是这样的:
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标准。允许提升。
答案 0 :(得分:1)
Proxy design pattern可以帮助解决这个问题。
典型的实现将定义一个类ValuePtr
,其行为就像普通的Value*
一样,即它有一个重载的operator->
和operator*
。但是这些运算符不是直接访问底层Value
对象,而是包含决定加载或重新计算实际值的逻辑。这种额外的间接级别将封装代理逻辑。
如果您需要将refences计算到其他对象,可能std::shared_ptr<Value>
可用作ValuePtr
中的underyling数据类型。
有关代码示例,请参阅this site。 Boost.Flyweight也可能会有所帮助。
答案 1 :(得分: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;
};