过度使用mutable来增强安全性?

时间:2014-12-04 04:51:21

标签: c++ pointers const mutable overuse

假设我有一个具有指针数组的类,并且我有一个方法取消引用指针并将其作为引用返回。我想允许方法调用者调用指针指向的对象的非const方法,但也希望保护自己免受调用者更改指针所指向的内容。如果我返回一个const引用,我必须将许多指针对象的方法标记为const,因此它的许多类成员变量都是可变的。

  1. 这是不好的做法吗?如果是这样,我该如何解决这个问题?
  2. 过度使用mutable是否存在性能损失?
  3. 示例:

    #include <iostream>
    #include <array>
    #include <memory>
    
    class Counter
    {
    public:
      Counter();
      void hit() const;
      void reset();
      unsigned count() const;
    private:
      mutable unsigned count_;
    };
    
    Counter::Counter() : count_(0) {}
    
    void Counter::hit() const { ++count_; }
    
    void Counter::reset() { count_ = 0; } 
    
    unsigned Counter::count() const { return count_; }
    
    class CircularArray
    {
    public:
      CircularArray();
      const Counter& next() const;
    private:
      mutable unsigned i_;
      std::array<std::unique_ptr<Counter>, 3> arr_;
    };
    
    CircularArray::CircularArray() : i_(2)
    {
      arr_[0] = std::unique_ptr<Counter>(new Counter);
      arr_[1] = std::unique_ptr<Counter>(new Counter);
      arr_[2] = std::unique_ptr<Counter>(new Counter);
    }
    
    const Counter& CircularArray::next() const { return *arr_[(i_ = (i_ + 1) % 3)]; }
    
    int main()
    {
      CircularArray circular;
      const Counter* p;
      p = &circular.next();
    
      p->hit();
      p->hit();
    
      Counter c;
      //*p = c; // <-- Want to prevent this
    }
    

1 个答案:

答案 0 :(得分:1)

为了扩展我所说的内容,滥用mutable就没有意义了。如果这是您想要阻止的全部内容:

*p = /* ... */;

然后通过删除Counter

的赋值运算符可以更轻松地完成它
class Counter
{
    void operator=(const Counter&) = delete;
    // ...
};

请记住,赋值运算符不会影响对象的标识:它不会更改其地址。语义上,涉及修改this对象以复制另一个对象的状态的赋值。事实上,即使你禁止我以某种方式使用赋值运算符,我仍然可以这样做:

// a very inefficient way of performing `*p = c`
p->reset();
while (p->count() != c.count())
    p->hit();

这实现了与执行任务完全相同的结果,尽管非常笨拙且效率低下。

执行赋值与调用接受类型为const Counter&的单个参数的非const成员函数没有什么不同。假设您可以重新定义赋值运算符,如果您愿意,则根本不做任何事情(尽管这可能是一个坏主意)。