C++ 中的易失性与可变性

volatile vs. mutable in C++

提问人:skydoor 提问时间:3/15/2010 最后编辑:Alex Bitekskydoor 更新时间:10/31/2013 访问量:52069

问:

我有一个关于易失性和可变性之间的区别的问题。我注意到这两者都意味着它可以更改。还有什么?它们是一回事吗?有什么区别?它们适用于哪些地方?为什么要提出这两个想法?如何以不同的方式使用它们?

多谢。

C++(英语:C++) 挥发性的 可变

评论


答:

23赞 Ben Voigt 3/15/2010 #1

它们绝对不是一回事。可变与 const 交互。如果您有 const 指针,则通常无法更改成员。可变提供了该规则的例外。

另一方面,Volatile 与程序所做的更改完全无关。这意味着内存可能会由于编译器无法控制的原因而更改,因此编译器每次都必须读取或写入内存地址,并且无法将内容缓存在寄存器中。

评论

0赞 jww 11/16/2015
“另一方面,Volatile 与程序所做的更改完全无关......” - 嗯,让成员易变,看看在编译过程中有什么中断。试图在事后添加易失性很像试图在事后添加常量......痛苦。
0赞 Ben Voigt 11/16/2015
@jww:这与程序的写入完全无关。您可以获取 类型的对象的地址,并将其存储到 a 中并从中读取。如果你制作那个对象,将其地址存储到其中将失败,即使你从未尝试写入。 程序代码中的更改/修改/内存写入是完全正交的。Tconst T*volatileconst T*volatile
28赞 xian 3/15/2010 #2

mutable:可变关键字覆盖任何封闭的 const 语句。可以修改 const 对象的可变成员。

volatile:volatile 关键字是与实现相关的修饰符,在声明变量时使用,可防止编译器优化这些变量。Volatile 应该与其值可能以意外方式(即通过中断)更改的变量一起使用,这可能与编译器可能执行的优化冲突。

评论

0赞 Asif Mushtaq 6/10/2015
你说我们应该更喜欢随机使用它吗?Volatile should be used with variables whose value can change in unexpected ways
0赞 Dan 11/16/2019
@AsifMushtaq不是价值观。方式。可变影响您编写的代码所具有的漏洞。因此,您可以通过 const ptr 或 const 引用访问变量。如果不是你的代码改变了它怎么办?编译器无法检查 ptr 或引用类型?这是不稳定的。易失性还会强制缓存写回主内存。因此,这在多线程代码中被大量使用。:)
121赞 Alex Martelli 3/15/2010 #3

即使在通过指针或引用访问的对象中,也可以在对象中更改字段,因此编译器知道不要将其存储在 R/O 内存中。位置是可以通过编译器不知道的代码(例如某些内核级驱动程序)更改的位置,因此编译器知道不要优化该值的寄存器分配,因为该值“不可能更改”,因为它上次加载到该寄存器中。向编译器提供非常不同类型的信息,以阻止非常不同类型的无效优化。mutableconstconstvolatile

评论

14赞 Mike DeSimone 3/15/2010
volatile对象也可以由完全不涉及 CPU 的进程更改。例如,通信外设中接收字节的寄存器可以在接收到字节时自行递增(这甚至可以触发中断)。另一个示例是外设中的挂起中断标志寄存器。
58赞 Michael Burr 3/15/2010
此外,这不仅意味着对象可以在编译器不知情的情况下进行更改,还意味着编译器无法消除对对象的写入,即使这些写入看起来毫无用处。例如:如果是易失性的,则编译器必须发出两个写入操作(这在硬件级别可能很重要)。但是,对于非易失性对象,编译器可以选择不费心编写 ,因为它从未被使用过。volatilex = 1; x = 0;x1
17赞 CTMacUser 5/25/2013
一个对象可以同时标记为 和 !你不能改变对象,但可以在你背后改变它。constvolatile
2赞 Michael Burr 5/7/2016
@Destructor:通常的情况是写入硬件设备寄存器。
6赞 iheanyi 5/24/2017
@Destructor let's say you are controlling the status of an LED. Write 0 turns it OFF, write 1 turns it ON. If I need to flash the LED to communicate some error status, but the compiler decides to optimize out all the writes except the last one, since none of the values are being used, then the LED never flashes and the behavior I desire is not realized.
11赞 Kyle Lutz 3/15/2010 #4

A variable marked allows for it to be modified in a method declared . mutableconst

A variable marked 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).volatile

19赞 Jonathan Leffler 3/15/2010 #5

A crude but effective way of thinking of the difference is:

  • The compiler knows when a mutable object changes.
  • The compiler cannot know when a volatile object changes.

评论

1赞 Mike DeSimone 3/15/2010
In that vein: bytes_received, reference_count.volatilemutable
5赞 BinCoder 10/31/2013 #6

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.

评论

2赞 KristianR 4/5/2014
No! This is a common misunderstanding. C++11 and C11 introduced atomics for this purpose stackoverflow.com/questions/8819095/…