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

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

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


当前回答

它允许区分按位的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,你的代码可能会更清晰,更易读。

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

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

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

在某些情况下(比如设计糟糕的迭代器),类需要保留一个计数或其他一些附带的值,这并不真正影响类的主要“状态”。这是我最常看到使用mutable的地方。如果没有mutable,您将被迫牺牲设计的整个const-ness。

对我来说,大多数时候这也像个黑客。在非常非常少的情况下有用。

mutmutable确实存在,因为你可以推断允许在一个常量函数中修改数据。

这样做的目的是,您可能有一个函数对对象的内部状态“什么都不做”,因此您将函数标记为const,但您可能确实需要以不影响其正确功能的方式修改一些对象的状态。

关键字可以作为对编译器的提示——理论上的编译器可以将一个常量对象(例如全局变量)放在内存中,并将其标记为只读。可变的存在提示不应该这样做。

下面是声明和使用可变数据的一些有效理由:

线程安全。声明一个可变的boost::mutex是完全合理的。 统计数据。给定函数的部分或全部实参,计算函数的调用次数。 记忆。计算一些代价高昂的答案,然后将其存储起来以备将来参考,而不是重新计算。

Mutable主要用于类的实现细节。类的用户不需要知道它,因此他认为“应该”是const的方法可以是。让互斥量可变的例子是一个很好的规范示例。

mutable关键字是一种戳穿对象上的const面纱的方法。如果你有一个指向对象的const引用或指针,你不能以任何方式修改该对象,除非它被标记为可变的。

使用const引用或指针,你被限制为:

仅对任何可见数据成员进行读访问 只调用标记为const的方法的权限。

可变异常使您现在可以编写或设置标记为可变的数据成员。这是唯一能从外部看到的区别。

在内部,那些对你可见的const方法也可以写入标记为可变的数据成员。本质上,const面纱是全面穿透的。完全由API设计者来确保mutable不会破坏const概念,并且只在有用的特殊情况下使用。mutable关键字有帮助,因为它清楚地标记了受这些特殊情况影响的数据成员。

在实践中,您可以在整个代码库中频繁地使用const(实际上您希望用const“疾病”“感染”代码库)。在这个世界中,指针和引用都是const的,只有极少数例外,从而产生的代码更容易推理和理解。一个有趣的题外话,请查阅“参考透明度”。

Without the mutable keyword you will eventually be forced to use const_cast to handle the various useful special cases it allows (caching, ref counting, debug data, etc.). Unfortunately const_cast is significantly more destructive than mutable because it forces the API client to destroy the const protection of the objects (s)he is using. Additionally it causes widespread const destruction: const_casting a const pointer or reference allows unfettered write and method calling access to visible members. In contrast mutable requires the API designer to exercise fine grained control over the const exceptions, and usually these exceptions are hidden in const methods operating on private data.

(注意:我多次提到数据和方法可见性。我说的是标记为public、private或protected的成员,这是这里讨论的完全不同类型的对象保护。)