0

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

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

例子:

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

1 回答 1

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&。假设您可以重新定义赋值运算符,如果您愿意,您可以完全不做任何事情(尽管这将是一个坏主意)。

于 2014-12-04T06:25:16.713 回答