不久前,我遇到了一些代码,它们用mutable关键字标记了一个类的成员变量。据我所知,它只是允许你在const方法中修改变量:
class Foo
{
private:
mutable bool done_;
public:
void doSomething() const { ...; done_ = true; }
};
这是唯一的使用这个关键字还是有更多的它比满足眼睛?从那以后,我在一个类中使用了这种技术,将boost::mutex标记为mutable,允许const函数出于线程安全的原因锁定它,但是,说实话,这感觉有点hack。
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的成员,这是这里讨论的完全不同类型的对象保护。)
Mutable将const的含义从按位的const更改为类的逻辑const。
这意味着具有可变成员的类将不再是按位的const,并且将不再出现在可执行文件的只读部分中。
此外,它通过允许const成员函数在不使用const_cast的情况下更改可变成员来修改类型检查。
class Logical {
mutable int var;
public:
Logical(): var(0) {}
void set(int x) const { var = x; }
};
class Bitwise {
int var;
public:
Bitwise(): var(0) {}
void set(int x) const {
const_cast<Bitwise*>(this)->var = x;
}
};
const Logical logical; // Not put in read-only.
const Bitwise bitwise; // Likely put in read-only.
int main(void)
{
logical.set(5); // Well defined.
bitwise.set(5); // Undefined.
}
请参阅其他答案了解更多细节,但我想强调的是,这不仅仅是为了类型安全,而且它会影响编译结果。