不久前,我遇到了一些代码,它们用mutable关键字标记了一个类的成员变量。据我所知,它只是允许你在const方法中修改变量:

class Foo  
{  
private:  
    mutable bool done_;  
public:  
    void doSomething() const { ...; done_ = true; }  
};

这是唯一的使用这个关键字还是有更多的它比满足眼睛?从那以后,我在一个类中使用了这种技术,将boost::mutex标记为mutable,允许const函数出于线程安全的原因锁定它,但是,说实话,这感觉有点hack。


当前回答

是的,这就是它的作用。我将它用于那些被方法修改的成员,而这些方法在逻辑上不会改变类的状态——例如,通过实现缓存来加速查找:

class CIniWrapper
{
public:
   CIniWrapper(LPCTSTR szIniFile);

   // non-const: logically modifies the state of the object
   void SetValue(LPCTSTR szName, LPCTSTR szValue);

   // const: does not logically change the object
   LPCTSTR GetValue(LPCTSTR szName, LPCTSTR szDefaultValue) const;

   // ...

private:
   // cache, avoids going to disk when a named value is retrieved multiple times
   // does not logically change the public interface, so declared mutable
   // so that it can be used by the const GetValue() method
   mutable std::map<string, string> m_mapNameToValue;
};

现在,你必须小心使用它——并发性问题是一个大问题,因为如果只使用const方法,调用者可能会认为它们是线程安全的。当然,修改可变数据不应该以任何重要的方式改变对象的行为,我给出的例子可能违反了这一点,例如,如果期望写入磁盘的更改将立即对应用程序可见。

其他回答

它允许区分按位的const和逻辑的const。逻辑const是指对象没有以通过公共接口可见的方式更改,就像锁定示例一样。另一个例子是一个类,它在第一次请求时计算一个值,并缓存结果。

因为c++11 mutable可以用在lambda上,表示用value捕获的东西是可修改的(默认情况下不是):

int x = 0;
auto f1 = [=]() mutable {x = 42;};  // OK
auto f2 = [=]()         {x = 42;};  // Error: a by-value capture cannot be modified in a non-mutable lambda

在为类测试目的创建存根时,mutable关键字非常有用。你可以存根一个const函数,仍然能够增加(可变的)计数器或任何你已经添加到存根的测试功能。这使存根类的接口保持不变。

经典的例子(在其他回答中提到),也是我迄今为止看到的使用mutable关键字的唯一情况,是用于缓存复杂的Get方法的结果,其中缓存是作为类的数据成员实现的,而不是作为方法中的静态变量(出于几个函数之间共享或简单清洁的原因)。

一般来说,使用mutable关键字的替代方法通常是方法中的静态变量或const_cast技巧。

另一个详细的解释在这里。

你对它的使用并不是一种hack,尽管像c++中的许多东西一样,mutable对于懒惰的程序员来说是一种hack,他们不想从头开始并将不应该是const的东西标记为非const。

Mutable用于在const方法中将特定属性标记为可修改的。这是它唯一的目的。在使用它之前要仔细考虑,因为如果你改变设计而不是使用mutable,你的代码可能会更清晰,更易读。

http://www.highprogrammer.com/alan/rants/mutable.html

所以如果上面的疯狂不是什么 可变是用来干什么的?这是 微妙的情况是:mutable是用于 对象在逻辑上的情况 不变,但在实践中需要 改变。这样的案例少而又远 两者之间,但它们确实存在。

作者给出的例子包括缓存和临时调试变量。