C++里的mutable关键字怎么用?(允许在const函数中修改成员)
技术百科
冰火之心
发布时间:2026-01-19
浏览: 次 mutable用于const成员函数中修改特定成员变量,适用于缓存、计数器、互斥锁等逻辑上不改变对象状态的场景,但不可修饰static、const或引用成员,且不保证线程安全与真正只读。
const成员函数里想改某个变量,但又不想去掉整个函数的const限定
这是 mutable 最典型、最合理的使用场景。C++ 规定:const 成员函数不能修改类的任何非静态数据成员,但 mutable 打破了这条限制——它明确告诉编译器:“这个成员变量,即使在 const 函数里也允许被修改”。关键在于:你得真有理由这么做,而不是为了绕过 const 约束而滥用。
哪些变量适合加 mutable?缓存、计数器、互斥锁
加 mutable 不是给所有变量开后门,而是服务于“逻辑上不改变对象状态”的需求。常见合法用途包括:
-
mutable std::mutex m_mutex:多线程中加锁/解锁不改变对象对外表现,但锁对象自身状态会变 -
mutable int m_access_count:记录某 const 函数被调用了多少次,不影响对象语义 -
mutable std::optiona:惰性计算并缓存结果,后续调用直接返回,逻辑仍是只读
l<:string> m_cached_result
错误用法示例:mutable std::string m_name,然后在 getName() const 里偷偷改名字——这违背了 const 的契约,编译器不会拦,但属于设计错误。
mutable 不能修饰 static、const 或引用成员
mutable 只能用于**非静态、非 const、非引用**的类内数据成员。以下写法都会编译失败:
class BadExample {
mutable static int s_val; // ❌ static 不行
mutable const int c_val = 42; // ❌ const 不行
mutable int& ref = other_var; // ❌ 引用不行
};
另外,mutable 对构造函数初始化列表没影响,但它修饰的成员仍需在初始化列表或默认成员初始化器中完成初始化(尤其像 std::mutex 这种无默认构造的类型)。
注意:mutable 成员的修改对 const 对象也生效
哪怕你有一个 const MyObj obj,只要它的某个成员是 mutable,你在 obj.someConstFunc() 里照样能改它。这意味着:
- 它不提供线程安全——多个线程同时调用同一个 const 函数,可能并发修改 mutable 成员
- 它不保证逻辑只读——如果你把 mutable 用在不该用的地方,const 对象的“不可变性”就只是假象
- 调试时容易忽略:断点停在 const 函数里改了 mutable 成员,但堆栈上看不到明显提示
真正难的不是语法怎么写,而是判断“这个修改是否真的不影响对象的逻辑状态”。一旦判断错了,mutable 就成了隐藏的 bug 温床。
# 这是
# 你在
# 多个
# 它不
# 适用于
# 你有
# 并发
# 对象
# 堆
# c++
# String
# int
# 构造函数
# access
# 线程
# 栈
# Static
# bug
# 多线程
# 成员变量
# 成员函数
# const
# 互斥
# 或引用
# mutable
# 上不
# 开后门
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- win11 OneDrive怎么彻底关闭 Win1
- 如何使用Golang reflect检查方法数量_
- Mac如何解压zip和rar文件?(推荐免费工具)
- c++的mutex和lock_guard如何使用
- 如何在 Django 中修改用户密码后保持会话不丢
- Windows10如何更改计算机工作组_Win10
- Win11怎么清理C盘下载文件夹_Win11清理下
- Win11关机快捷键是什么_Win11快速关机方法
- Windows服务启动类型恢复方法_错误修改导致的
- Python对象比较排序规则_集合使用说明【指导】
- mac怎么安装字体_MAC添加第三方字体与字体册管
- windows系统找不到无线网络怎么办_windo
- php中常量能用::访问吗_类常量与作用域操作符使
- Windows10怎样设置家长控制_Windows
- Win10如何卸载微软拼音输入法 Win10只保留
- php做exe支持多线程吗_并发处理实现方式【详解
- Win11怎么设置右键刷新选项_Windows11
- Go语言中slice追加操作的底层共享机制解析
- 如何在Golang中修改数组元素_通过指针实现原地
- Windows10电脑怎么设置电源按钮_Win10
- 如何在 Go 中正确反序列化 XML 多节点数组(
- Win11文件扩展名怎么显示 Win11查看文件后
- Win11摄像头无法使用怎么办_Win11相机隐私
- 用lighttpd能运行php吗_lighttpd
- Win10电脑怎么设置网络名称_Windows10
- Windows怎样关闭Edge新标签页广告_Win
- SAX解析器是什么,它与DOM在处理大型XML文件
- Mac如何彻底清理浏览器缓存?(Safari与Ch
- 如何在 Go 中正确反序列化多个同级 XML 元素
- Windows如何设置登录时的欢迎屏幕背景?(锁屏
- Win10怎样卸载TeamViewer_Win10
- php打包exe后无法写入文件_权限问题解决方法【
- 如何在Golang中实现并发消息队列消费者_Gol
- c++ std::atomic如何保证原子性 c+
- php命令行怎么运行_通过CLI模式执行PHP脚本
- Windows10系统怎么查看显卡驱动_Win10
- Win11时间格式怎么改成12小时制 Win11时
- C++如何使用Qt创建第一个GUI窗口?(入门教程
- 如何在Golang中处理模块包路径变化_Golan
- Win11怎么关闭透明效果_Windows11个性
- 静态属性修改会影响所有实例吗_php作用域操作符下
- Win11如何卸载OneDrive_Win11卸载
- c++中explicit(bool)的用法 c++
- Python抽象类与接口设计_规范说明【指导】
- 如何开启Windows的远程服务器管理工具(RSA
- Win11怎么忘记WiFi网络_Win11删除已保
- Win11怎么修改DNS服务器 Win11设置DN
- Win11怎么设置任务栏图标大小_Windows1
- Python数据抓取合法性_合规说明【指导】
- Mac如何使用听写功能_Mac语音输入打字【效率技


QQ客服