处理C ++类中的延迟计算

时间:2009-05-19 05:39:31

标签: c++ const lazy-evaluation mutable

假设我有一个班级:

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_;
}

我觉得这是糟糕的设计。还有更好的方法吗?

4 个答案:

答案 0 :(得分:11)

这完全是做到这一点的方式。 Const可以表示二进制const,或者它可以表示概念上的const。使用可变意味着你要做的更晚,这很好。

答案 1 :(得分:4)

为了帮助理解使用mutable的原因,我们可以探索其他选项。

您可以使用 const_cast 解决同样的问题:

size_t NumberCollection::difficultSize() const
{
     if(!upToDate_)
     {
          NumberCollection& nonConst = const_cast<NumberCollection&>(*this);
          nonConst.difficultSet_ = PerformExpensiveCalculationFunction();
          nonConst.upToDate_ = true;
     }
     // etc....
}

提供此解决方案之后,我会说它不如使用 mutable 。如果一个成员被标记为 mutable ,那么只需查看标题我就可以收集你如何处理它。如果您使用 const_cast ,我不会收到此信息。

但是有人可能会接受辩论的另一面,并说最好不要在标题中公开实现细节。

答案 2 :(得分:3)

这基本上是C ++具有可变构造的原因。 Alan De Smet关于滥用mutable的rant显示了不应使用mutable的各种情况。

在这种情况下,difficultySize()不会更改NumberCollection所代表的内容 - 这适用于标记为const。它确实需要有时更改内部,这就是为什么你需要将difficultSet_和upToDate_标记为可变的。

答案 3 :(得分:1)

您的解决方案在C ++ 98中很好。请注意,在C ++ 11中,您应该考虑同步对可变数据的访问。否则,当您的类被STL使用时,您可能会遇到问题,这假定所有const成员函数都是线程安全的。

有关详细信息,请参阅Does const mean thread-safe in C++11?