过度使用可变可增强安全性



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

  1. 这是不好的做法吗?如果是这样,我该如何解决这个问题?
  2. 过度使用可变变量是否会对性能造成损失?

例:

#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
}

扩展一下我所说的,为此滥用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 成员函数没有什么不同。 假设,如果您愿意,您可以将赋值运算符重新定义为完全不执行任何操作(尽管这是一个坏主意)。

最新更新