mutable关键字
mutable 关键字
在 C++ 中,mutable 是一个类型修饰符,允许类的成员变量在 const 对象 或 const 成员函数 中被修改。
- 用途:修改内部缓存、统计访问次数等,但不改变类的逻辑状态(logical constness)。
- 原因:
const成员函数保证对象逻辑上不变,但mutable允许在物理上修改部分内部数据。
基本语法
class MyClass {
public:
mutable int counter;
void increase() const {
++counter; // 合法,尽管是 const 函数
}
};
-
counter被声明为mutable,即使是在const成员函数中,也允许对它进行修改。 -
increase()是const函数,它不能修改除mutable成员以外的任何数据成员。
使用场景
在 const 成员函数中做缓存或懒加载
// 一个带缓存功能的类,使用 mutable 实现懒计算(lazy evaluation)
class CachedValue {
private:
// 标志变量:表示是否已经计算过结果
// 因为会在 const 函数中修改,必须加 mutable 修饰
mutable bool computed = false;
// 缓存的计算结果,初始值为 0
// 也是需要在 const 函数中被修改,所以加 mutable
mutable int cache = 0;
public:
// 返回计算值的函数,逻辑上是 const 的:对外接口不会改变对象的状态
int getValue() const {
// 如果还没计算过,就计算一次并缓存结果
if (!computed) {
cache = expensiveCalculation(); // 修改了 mutable 成员
computed = true; // 标记为已计算
}
// 返回缓存的结果
return cache;
}
private:
// 实际的计算逻辑(模拟耗时操作)
int expensiveCalculation() const {
return 42;
}
};
-
虽然
getValue()是const,但它需要修改computed和cache,这些变量被声明为mutable以绕过编译器的限制。 -
这是典型的懒计算缓存模式。
日志记录或统计访问次数
class Logger {
private:
mutable int accessCount = 0;
public:
void print() const {
++accessCount;
std::cout << "Access #" << accessCount << std::endl;
}
};
和 const_cast 区别
| 特性 | mutable |
const_cast |
|---|---|---|
| 用途 | 成员变量在 const 对象中可修改 | 去除对象的 const 修饰符 |
| 编译期安全 | 是 | 否,若修改真正 const 对象会导致未定义行为 |
| 推荐使用程度 | 安全合理使用没问题 | 小心使用,容易出错 |
常见陷阱
-
不要滥用
mutable。它破坏了const的“承诺”,应仅在有充分理由的情况下使用。 -
线程安全问题。如果
mutable成员在多线程下被修改,可能导致竞态条件。 -
mutable只能用于类的非静态成员变量,不能修饰局部变量、静态变量、函数或参数等。-
为什么不能用于局部变量?
局部变量本身没有
const对象约束,根本就不需要mutable:void func() { mutable int x = 0; // 编译不通过 }局部变量随时可以修改,它从来不会受到
const的约束,所以mutable没有任何意义,自然也被语言禁止使用。 -
为什么不能用于函数?
函数不是变量,
mutable修饰的是变量的可变性,不能用于函数。mutable int getValue(); // 语法错误如果想表达“这个函数在
const对象上也能调用”,应该用const修饰函数,而不是mutable:int getValue() const; // 表示此函数不会修改对象状态 -
为什么不能用于函数参数?
因为函数参数也是局部变量,它们没有
const对象语义,也不需要mutable。void func(mutable int x); // 错误而如果希望参数不可修改,可以用
const修饰:void func(const int x); // 表示 x 不可修改(传值没意义,传引用才重要) -
为什么不能用于静态成员变量?
静态成员变量是类级别的变量,不依赖于具体对象,不受
const对象的影响。class A { mutable static int count; // 错误,mutable 不能用于 static 成员 };const对象是指某个具体对象不可修改,而static变量与具体对象无关。- 所以,即使某个对象是
const,依然可以修改类的static变量(前提是没有被const修饰)。
class A { static int count; void modify() const { ++count; // 合法,即使是在 const 函数中 } };
-

浙公网安备 33010602011771号