4

假设我有一堂课:

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

Whereinsert()添加一个元素到easySet_. difficultSet_的成员根据 的成员而变化easySet_

我遇到的问题是,多次插入意味着difficultSet_不断重新计算。所以我想difficultSet_被懒惰地计算(即只有当difficultBegin(), difficultEnd(), ordifficultSize()被调用时)。问题是,那我其实得把它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

4 回答 4

12

这完全是这样做的。const 可以表示二进制 const,也可以表示概念上的 const。使用 mutable 意味着你正在做后者,这很好。

于 2009-05-19T05:49:45.863 回答
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 ,我不会得到此信息。

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

于 2009-05-19T06:12:38.440 回答
3

这本质上是 C++ 具有可变结构的原因。Alan De Smet 关于 mutable 滥用的咆哮表明了不应该使用 mutable 的情况。

在这种情况下,difficultSize() 不会改变 NumberCollection 所代表的内容——它适合标记为 const。它有时需要更改内部结构,这就是为什么您需要将 hardSet_ 和 upToDate_ 标记为可变的原因。

于 2009-05-19T05:55:33.673 回答
1

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

有关更多详细信息,请参阅是否 const 意味着 C++11 中的线程安全?

于 2013-01-04T00:08:35.987 回答