mutable 意为可变的,可以在非引用非常量非静态数据成员的声明中出现,允许被常量类对象修改。
类中的 mutable
先聊聊一个有趣的话题,关于 const 类成员函数有两大观点流派:
bitwise constness:主张成员函数只有在不更改对象的任何非静态成员变量时才被认为是 const,即绝对常量;
事实上这正是 C++ 对常量性的定义。
logical constness:主张 const 成员函数可以修改所处理对象内部的某些 bits,仅当用户看不出的情况才行,即自适应常量;
对于第一种主张,有些成员函数并不具备 bitwise 特性,却能通过编译,一个很直观的例子便是,一个 const 类成员函数修改了类中某个指针指向的内容,却没有改变其指向:
1class TextBlock {
2 public:
3 TextBlock(const char* s) { /* ... */ }
4
5 char& operator[](std::size_t index) const {
6 return pText[index];
7 }
8
9 private:
10 char* pText;
11};
12
13int main() {
14 const TextBlock t("hello");
15 char* ptr = &t[0];
16 *ptr = 'j';
17}
于是一个保有字符串 "hello" 的常量对象,并没有拿牢,而是被改为了 "jello"。
对于第二种主张,编译器并不支持这一做法,于是 mutable 关键字派上用场。如果将一个成员变量声明为 mutable(保证声明前提),则可以在 const 成员函数中对其进行修改,如下:
1class Foo {
2 public:
3 /* ... */
4 int AddAndGet() const { return ++bar; }
5 private:
6 mutable int bar; // 释放 bitwise constness 约束
7};
主要用于指定不影响类的外部可观察状态的成员,通常在并发场景下搭配互斥锁使用。
lambda 表达式中的 mutable
具体可参考本文。
简单来说就是 lambda 表达式会将值捕获的变量视为 const,若想要对其进行修改需加上 mutable 说明符。