罗剑锋的 C++ 实战笔记
罗剑锋
前奇虎 360 技术专家,Nginx/OpenResty 开源项目贡献者
35514 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 32 讲
结束语 (1讲)
罗剑锋的 C++ 实战笔记
15
15
1.0x
00:00/00:00
登录|注册

07 | const/volatile/mutable:常量/变量究竟是怎么回事?

给函数的返回值加上const,也就是说返回一个常量对象,有什么好处?
学完了这节课,你觉得今后应该怎么用const呢?
用来修饰成员变量,允许const成员函数修改,但要小心不要误用损坏对象
表示变量可能会被“不被察觉”地修改,禁止编译器优化,应当少用
修饰成员函数,表示函数是“只读”的,const对象只能调用const成员函数
修饰引用和指针,常量引用是函数入口参数的最佳类型
可以给任何对象附加上“只读”属性,保证安全
对于const对象相关的代码,如果成员函数不是const,就不允许调用
const成员函数的执行过程是const的,不会修改对象的状态
“*”两边都有const,表示指针不能被修改,且指向的变量也不能被修改
const在“*”的右边,表示指针不能被修改,而指向的变量可以被修改
const放在声明的最左边,表示指向常量的指针
在设计函数的时候,建议尽可能使用它作为入口参数,保证效率和安全
可以引用任何类型,且会给变量附加上const特性
思考题
mutable
volatile
const
标记为mutable的成员不会改变对象的状态,允许const成员函数改写mutable成员变量
mutable表示变量即使是在const对象里,也是可以修改的
const成员变量和const成员函数
常量指针
常量引用
volatile表示变量的值可能会以“难以察觉”的方式被修改,禁止编译器做任何形式的优化
const定义的常量在运行期间不会改变,编译器会采取一些优化手段
const定义的常量在预处理阶段并不存在,而是直到运行阶段才会出现
课下作业
小结
关键字mutable
与类相关的const用法
基本的const用法
const与volatile
const/volatile/mutable:常量/变量究竟是怎么回事?

该思维导图由 AI 生成,仅供参考

你好,我是 Chrono。
上节课我讲了自动类型推导,提到 auto 推导出的类型可以附加 const、volatile 修饰(通常合称为“cv 修饰符”)。别看就这么两个关键字,里面的“门道”其实挺多的,用好了可以让你的代码更安全、运行得更快。今天我就来说说它们俩,以及比较少见的另一个关键字 mutable。

const 与 volatile

先来看 const 吧,你一定对它很熟悉了。正如它的字面含义,表示“常量”。最简单的用法就是,定义程序用到的数字、字符串常量,代替宏定义
const int MAX_LEN = 1024;
const std::string NAME = "metroid";
但如果我们从 C++ 程序的生命周期角度来看的话,就会发现,它和宏定义还是有本质区别的:const 定义的常量在预处理阶段并不存在,而是直到运行阶段才会出现
所以,准确地说,它实际上是运行时的“变量”,只不过不允许修改,是“只读”的(read only),叫“只读变量”更合适。
既然它是“变量”,那么,使用指针获取地址,再“强制”写入也是可以的。但这种做法破坏了“常量性”,绝对不提倡。这里,我只是给你做一个示范性质的实验,还要用到另外一个关键字 volatile。
// 需要加上volatile修饰,运行时才能看到效果
const volatile int MAX_LEN = 1024;
auto ptr = (int*)(&MAX_LEN);
*ptr = 2048;
cout << MAX_LEN << endl; // 输出2048
可以看到,这段代码最开始定义的常数是 1024,但是输出的却是 2048。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

C++中的const、volatile和mutable关键字在代码优化和安全性方面发挥着重要作用。const关键字定义常量,但在运行时仍可通过指针进行修改,而volatile关键字则禁止编译器对变量进行优化,每次使用时都需重新获取其值。在C++中,const还可用于常量引用和常量指针,以确保变量只读不可修改。此外,const成员函数表示函数执行过程是const的,不会修改对象的状态,与常量引用和常量指针相结合,可确保对象的安全性和代码的优化。文章还提到了const在类中的应用,以及对const、volatile和mutable的综合理解。文章内容涵盖了C++中const、volatile和mutable的基本用法和与类相关的应用,对读者快速了解这些关键字的作用和用法具有指导意义。此外,文章还介绍了mutable关键字,它允许const成员函数修改成员变量,但需要谨慎使用以避免损坏对象。总结来说,尽可能多用const可以让代码更安全,特别在多线程编程时尤其有用。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《罗剑锋的 C++ 实战笔记》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(28)

  • 最新
  • 精选
  • 无止境
    c++的指针和引用有啥区别老师?

    作者回复: 简单来说,指针是内存地址,引用是变量别名,指针可以是空,而引用不能为空。

    2020-05-21
    9
    37
  • Bluebuger
    volatile 在底层用的多,驱动、裸机开发这类。由于外部硬件设备,有部分处理器设计时候直接映射的内存地址,所以除了软件可以修改,硬件可能修改,所以需要让编译器不去优化这样的变量,必须从源头重新取值。

    作者回复: 对,volatile在底层开发的时候用的比较多,一般做上层应用开发、比如服务器、UI就很少用了。

    2020-06-17
    2
    16
  • 奋斗
    《1》volitate: cpu每次读取数据的时候,如果寄存器或者三级缓存中有该值,则直接使用,所以此时如果内存中的值被改变,值不会改变。如果加上volitate每次绕过寄存器和缓存直接从内存读取,此时内存中的值已经改变了。 《2》mutable: 1、在lambal表达式中,如果捕获按值捕获,但是在函数体中想要修改,可以使用mutable 2、多线程环境下如果某个成员函数,比如int get_count() const { },返回类中某个成员数量,势必会进行加锁保护变量达到线程安全,此时声明mutex必须是mutable的。 int get_count() const { std::lock_guard<std::mutex> lock(m) return count; } 在声明mutable std::mutex m; 需要加 mutable

    作者回复: 总结的非常好,awsome。

    2021-05-25
    12
  • EncodedStar
    用好const 记住文章中的“ “const &”可以引用任何类型,是函数入口参数的最佳类型” 是重点

    作者回复: 这个是一个通用准则,但对于int、double这样小而简单的类型就有点“重”,int这样的内建类型可以直接用const T。 Boost库里有一个call_traits,它可以推导出最佳类型。

    2020-05-22
    12
  • 罗杰
    C++ 中volatile 关键字, 我感觉最关键的是要知道, 他根本不构成 同步语义, 多线程编程中要杜绝使用. 记得之前看过一个资料, volatile 从C++ 标准中出现的原因是 为了解决 "硬件映射到内存上..." 的问题, 也就是说 一般的开发者, 根本不会涉及到这一块. java 中 volatile 和 C++ 中的 volatile 还不一样, java 中的volatile 是构成 happen-before的, 是可以使用在多线程编程当中的

    作者回复: 说得很好,一定不要把其他语言的经验简单地套用到C/C++里,特别是volatile这个关键字,差异非常大。

    2020-08-04
    2
    7
  • Stephen
    "const 定义的常量在预处理阶段并不存在,而是直到运行阶段才会出现。",老师,那编译阶段它也没有出现吗?

    作者回复: 是的,const常量本质上是变量,那么必然就是在运行阶段分配内存才能出现。 但现在很多时候编译器会对const常量做优化,允许在编译阶段使用,但必须要说这并不是const常量的本意。

    2020-07-31
    2
    7
  • IMBFD
    前辈在const函数那里为什么不说明其实是const修饰了this呢?这样就很好解释了

    作者回复: 单从成员函数的形式上来看,是看不到this指针的,我怕这么说会让有的同学更糊涂,所以就先简单地说一下,把详细的解释放在了小贴士里。

    2020-09-08
    3
  • 宇天飞
    学完了这节课,你觉得今后应该怎么用 const 呢? 1、修饰常量、成员变量、成员函数 2、修饰类的时候注意const成员以及可变成员 给函数的返回值加上 const,也就是说返回一个常量对象,有什么好处? 使用更方便,防止意外修改

    作者回复: 学习的进展很快啊,不过还是要适当保持节奏,留一点思考的时间,欲速则不达。

    2020-09-01
    3
  • 范闲
    1. effecttive里主要的用处就是const替换define,const成员函数,const &入参 2.返回常量对象就是实际上保持了内部状态的不可变。不受外部影响,实际上也是不希望外部改变对象

    作者回复: 说的挺好的,其实在effective 里对const也花了很多的篇幅,用好const真的能够让代码更安全。

    2020-05-21
    3
  • 木须柄
    万能引用 (universal reference) 一般是指在函数模板时传入的 "T&&" 这种形参形式,主要作用是用来同时匹配左值和右值实参的传入,这里我觉得罗老师更多是借用了这个概念,主旨是为了说明 "const &" 使用的广泛性

    作者回复: 在T&&出现之前,const&的确是万能引用,不过自从C++11新增了右值,“万能”的这个头衔就只能“让贤”了,笑。

    2021-10-04
    2
收起评论
显示
设置
留言
28
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部