C++ 中的易失性与可变性
我有一个关于易失性和可变性之间区别的问题。我注意到这两者都意味着它可以改变。还有什么?它们是同一件事吗?有什么区别?它们适用于哪些地方?为什么提出这两个想法?如何以不同的方式使用它们?
多谢。
I have a question about the difference between volatile and mutable. I noticed that both of the two means that it could be changed. What else? Are they the same thing? What's the difference? Where are they applicable? Why the two ideas are proposed? How to use them in different way?
Thanks a lot.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
即使在通过 const 指针或引用访问的对象中,或者在 const 对象中,也可以更改
mutable
字段,因此编译器不知道将其存储在 R/O 内存中。易失性位置是可以被编译器不知道的代码(例如某些内核级驱动程序)更改的位置,因此编译器知道不要优化例如无效情况下该值的寄存器分配假设该值自上次加载到该寄存器以来“不可能已更改”。向编译器提供非常不同类型的信息来阻止非常不同类型的无效优化。A
mutable
field can be changed even in an object accessed through aconst
pointer or reference, or in aconst
object, so the compiler knows not to stash it in R/O memory. Avolatile
location is one that can be changed by code the compiler doesn't know about (e.g. some kernel-level driver), so the compiler knows not to optimize e.g. register assignment of that value under the invalid assumption that the value "cannot possibly have changed" since it was last loaded in that register. Very different kind of info being given to the compiler to stop very different kinds of invalid optimizations.mutable
:mutable 关键字会覆盖任何封闭的 const 语句。 const 对象的可变成员可以被修改。易失性
:易失性关键字是一个依赖于实现的修饰符,在声明变量时使用,它可以防止编译器优化这些变量。易失性应该与其值可能以意外方式(即通过中断)改变的变量一起使用,这可能与编译器可能执行的优化发生冲突。来源
mutable
: The mutable keyword overrides any enclosing const statement. A mutable member of a const object can be modified.volatile
: The volatile keyword is an implementation-dependent modifier, used when declaring variables, which prevents the compiler from optimizing those variables. Volatile should be used with variables whose value can change in unexpected ways (i.e. through an interrupt), which could conflict with optimizations that the compiler might perform.Source
它们绝对不是同一件事。 Mutable 与 const 交互。如果您有 const 指针,通常无法更改成员。 Mutable 为该规则提供了一个例外。
另一方面,易失性与程序所做的更改完全无关。这意味着内存可能会因编译器无法控制的原因而发生变化,因此编译器必须每次都读取或写入内存地址,并且无法将内容缓存在寄存器中。
They are definitely NOT the same thing. Mutable interacts with const. If you have a const pointer, you normally could not change members. Mutable provides an exception to that rule.
Volatile, on the other hand, is totally unrelated to changes made by the program. It means that the memory could change for reasons beyond the control of the compiler, therefore the compiler has to read or write the memory address every time and can't cache the content in a register.
考虑差异的一个粗略但有效的方法是:
A crude but effective way of thinking of the difference is:
标记为
mutable
的变量允许在声明为const
的方法中对其进行修改。标记为 易失性 的变量告诉编译器,每次您的代码也告诉它时,它必须读/写该变量(即它无法优化对变量的访问)。
A variable marked
mutable
allows for it to be modified in a method declaredconst
.A variable marked
volatile
tells the compiler that it must read/write the variable every time your code tells it too (i.e. it cant optimize away accesses to the variable).我想补充一点,在处理多线程应用程序时,易失性也非常有用,即,您有主线程(main() 所在的位置),并且您生成一个工作线程,当变量“app_running”为 true 时,该线程将继续旋转。 main() 控制“app_running”的真假,因此如果没有在“app_running”的声明中添加 volatile 属性,如果编译器优化了辅助线程运行的代码中对“app_running”的访问,main( )可能会将“app_running”更改为 false,但辅助线程将继续运行,因为该值已被缓存。我在 Linux 和 VisualC++ 上使用 gcc 看到了相同的行为。 “app_running”声明中的“易失性”属性解决了这个问题。因此,在这种情况下,不会涉及硬件中断或内核来更改此类变量的值。
I would like to add that volatile is also very useful when dealing with multithreading applications, i.e, you have your main thread (where main() lives) and you spawn a worker thread that will keep spinning while a variable "app_running" is true. main() controls whether "app_running" is true or false, so if you do not add the volatile attribute to the declaration of "app_running", if the compiler optimizes access to "app_running" in the code ran by the secondary thread, main() might change "app_running" to false but the secondary thread will keep running because the value has been cached. I have seen the same behavior using gcc on Linux and VisualC++. A "volatile" attribute put in "app_running" declaration solved the problem. So, this is scenario where no hardware interrupts or kernel is invoved in changing the value of such variables.