我对volatile和mutable之间的区别有疑问。我注意到两者都意味着可以对其进行更改。还有什么?它们是一样的吗?有什么不同?它们在哪里适用?为什么提出这两个想法?如何以不同方式使用它们?
非常感谢。
Answers:
甲mutable
字段即使在通过访问的对象来改变const
指针或引用,或在一个const
对象,所以编译器知道不藏匿它R / O存储器。一个volatile
位置是一个可以通过代码编译器不知道的(例如,一些内核级驱动程序)来改变,所以编译器不知道的无效假设值“不可能有下该值的优化如寄存器分配已更改”,因为它最后一次加载到该寄存器中。提供给编译器的信息截然不同,以停止截然不同的无效优化。
volatile
不仅意味着对象可以在编译器不了解的情况下进行更改-这还意味着编译器无法消除对该对象的写入,即使这些写入似乎是无用的。例如:x = 1; x = 0;
如果x
是易失性的,则编译器必须发出两个写操作(这在硬件级别可能很重要)。但是,对于非易失性对象,编译器可以选择不打扰编写,1
因为它从未使用过。
const
和volatile
!您无法更改对象,但是可以在背后进行更改。
mutable
:mutable关键字会覆盖所有封闭的const语句。const对象的可变成员可以被修改。
volatile
注意:volatile关键字是依赖于实现的修饰符,在声明变量时使用,这可防止编译器优化这些变量。易失性应与变量的值可能以意想不到的方式(即通过中断)改变的变量一起使用,这可能与编译器可能执行的优化冲突。
Volatile should be used with variables whose value can change in unexpected ways
我们应该更喜欢随机使用它吗?
他们绝对不是同一回事。可变与const交互。如果您有const指针,则通常无法更改成员。可变为该规则提供了一个例外。
另一方面,易失性与程序所做的更改完全无关。这意味着内存可能会由于编译器无法控制的原因而发生变化,因此编译器每次都必须读取或写入内存地址,并且无法将内容缓存在寄存器中。
T
,并将其存储到中const T*
并从中读取。如果创建该对象volatile
,const T*
即使您从未尝试写入它,也无法将其地址存储到其中。 volatile
程序代码的更改/修改/内存写入是完全正交的。
粗略而有效的差异思考方法是:
volatile
依此类推:bytes_received,mutable
reference_count。
标记mutable
为变量的变量允许在声明的方法中对其进行修改const
。
标记为变量的变量volatile
告诉编译器,每次您的代码也告诉变量时,它必须读/写变量(即,它不能优化对变量的访问)。
我想补充一点,在处理多线程应用程序时,volatile也非常有用,例如,您拥有主线程(main()所在的位置),并且生成了一个工作线程,该工作线程将在变量“ app_running”为true时保持旋转。main()控制“ app_running”是true还是false,因此,如果不将volatile属性添加到“ app_running”的声明中,则如果编译器在辅助线程main(( )可能会将“ app_running”更改为false,但辅助线程将继续运行,因为该值已被缓存。我已经在Linux和VisualC ++上使用gcc看到了相同的行为。放入“ app_running”声明中的“ volatile”属性解决了该问题。所以,
volatile
也可以通过根本不涉及CPU的进程来更改对象。例如,通信外设中接收字节的寄存器可以在接收到字节后自身增加(这甚至可能触发中断)。另一个示例是外设中的挂起中断标志寄存器。