在C ++类与懒惰计算处理
-
22-08-2019 - |
题
让我们说我有一个类:
class NumberCollection
{
public:
typedef std::set<int> SetType;
typedef SetType::iterator iterator;
void insert(int n);
iterator begin();
iterator end();
size_t size() const;
iterator difficultBegin();
iterator difficultEnd();
size_t difficultSize() const;
private:
SetType easySet_, difficultSet_;
}
其中insert()
增加easySet_
的元件。 difficultSet_
成员的变化取决于easySet_
的成员。
我遇到的问题是,多个插入意味着difficultSet_
不断重新计算。所以我想懒洋洋地计算difficultSet_
(即difficultBegin()
,difficultEnd()
,或difficultSize()
被称为只有当)。问题是,然后我实际上是使difficultSet_
成mutable
否则difficultSize()
不能操作就可以了。
所以,现在我的类的声明看起来像
class NumberCollection
{
public:
typedef std::set<int> SetType;
typedef SetType::iterator iterator;
void insert(int n);
iterator begin();
iterator end();
size_t size() const;
iterator difficultBegin();
iterator difficultEnd();
size_t difficultSize() const;
private:
SetType easySet_;
mutable SetType difficultSet_;
mutable bool upToDate_;
}
我觉得这是不好的设计,但。有没有更好的办法?
解决方案
这是完全做到这一点的方式。常量可以表示二进制的常量,或者它可能意味着概念常量。使用可变意味着你正在做后期,这是很好的。
其他提示
要帮助理解为什么要使用可变的,我们可以探索其他选项。
可以使用解决同样的问题的的const_cast :
size_t NumberCollection::difficultSize() const
{
if(!upToDate_)
{
NumberCollection& nonConst = const_cast<NumberCollection&>(*this);
nonConst.difficultSet_ = PerformExpensiveCalculationFunction();
nonConst.upToDate_ = true;
}
// etc....
}
已经提出了这样的解决方案,我会说,这是不如使用可变。如果一个成员被标记为的可变的,则简单地通过看头我可以收集你如何处理它。如果你使用的的const_cast 我没有得到这个信息。
但随后有人可能采取辩论的另一面,并说,这是最好不要在标题中暴露的实现细节。
这基本上是C ++具有可变结构的原因。艾伦·迪斯的咆哮了解的可变滥用显示了种情况中,可变不应当被使用。
在这种情况下,difficultSize()不改变什么NumberCollection表示 - 它适合于标记为const。它是如何以往任何时候都需要改变的时候了内部,这就是为什么你需要标记difficultSet_和upToDate_为可变的。
您的解决方案是在C ++ 98细。请注意,在C ++ 11,你应该考虑到访问您的可变数据同步。否则,在你的类使用STL,它假定所有的const成员函数是线程安全的,你可能会遇到问题。
有关进一步详情,请参阅是否意味着常量线程安全在C ++ 11?