mutable只能修饰类内成员变量或lambda捕获,必须紧邻类型声明,不可与const同修饰同一变量,不解除访问控制,也不保证线程安全。

mutable 修饰类成员变量时必须紧挨着类型声明
它只能出现在类定义内部的成员变量声明前,不能放在函数参数、局部变量或全局变量上。位置错一点——比如写在 const 后面、或者放在访问控制符之后但没紧贴类型——编译器直接报错。
-
mutable int cache_valid_;✅ 正确:mutable紧接类型 -
int mutable cache_valid_;❌ 错误:顺序颠倒,不识别 -
class Foo { public: mutable int x; };✅ 可以跨访问控制符,但仍是变量声明的一部分 -
mutable std::string data_ = "hello";✅ C++11 起支持带默认初始化
mutable 不能和 const 同时修饰同一个成员变量
这会触发编译错误,因为语义冲突:const 表示“不可变”,mutable 表示“即使在 const 函数里也能变”。两者同时出现,编译器不知道听谁的。
-
const mutable int x;❌ 编译失败,error: 'mutable' and 'const' cannot be used together -
mutable const int* p;✅ 允许:这里const修饰的是指针所指内容(*p不可改),mutable修饰的是指针本身(p可改) - 常见误写是给
const成员函数里的局部变量加mutable—— 没用,也不合法
lambda 表达式中 mutable 写在参数列表后、函数体前
这是唯一一种 mutable 不修饰变量声明的用法,它作用于整个 lambda 的捕获副本,让按值捕获的变量可修改。
-
int x = 42; auto f = [=]() mutable { ++x; return x; };✅mutable在()后、{前 -
auto f = [=] mutable { ... };❌ 缺少括号,语法错误 - 没写
mutable时,=捕获的变量在 lambda 体内是const副本,连++都不被允许
容易忽略的细节:mutable 成员仍受访问控制约束
mutable 只解除 const 函数对修改权限的限制,不绕过 private 或 protected。外部代码依然不能直接读写 private mutable 成员。
- 哪怕
mutable int counter_;是private,外部调用obj.counter_ = 100;仍编译失败 - 只有类内(包括 const 成员函数)才能修改它
- 多线程下,
mutable不提供任何同步保障;想安全修改,得配mutable std::mutex或原子类型
实际写的时候,最常踩的坑就是把 mutable 当成“全局可写开关”——它只松动 const 限制,其他规则一条没少。位置、搭配、作用域,三者缺一不可。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











