C++中的volatile与mutable

sky*_*oor 84 c++ mutable volatile

我对volatile和mutable之间的区别有疑问.我注意到这两个都意味着它可以改变.还有什么?它们是一样的吗?有什么不同?它们适用于哪里?为什么提出这两个想法?如何以不同的方式使用它们?

非常感谢.

Ale*_*lli 111

mutable字段即使在通过访问的对象来改变const指针或引用,或在一个const对象,所以编译器知道不藏匿它R/O存储器.一个volatile位置是一个可以通过代码编译器不知道的(例如,一些内核级驱动程序)来改变,所以编译器知道没有优化如无效的假设下寄存器值的分配的值"不可能有改变了"因为它最后一次加载到该寄存器中.为编译器提供了非常不同类型的信息,以阻止非常不同类型的无效优化.

  • 另外,`volatile`不仅意味着对象可以在编译器知识之外进行更改 - 这也意味着编译器无法消除对对象的写入,即使这些写入看起来没用.例如:`x = 1; x = 0;`如果`x`是易失性的,编译器必须发出两个写操作(这在硬件级别可能很重要).但是,对于非易失性对象,编译器可以选择不打扰写入"1",因为它从未使用过. (54认同)
  • `volatile`对象也可以由不涉及CPU的进程改变.例如,通信外设中的字节接收寄存器可以在接收到一个字节时自行递增(这甚至可以触发中断).另一个例子是外设中的挂起中断标志寄存器. (13认同)
  • 一个对象可以标记为`const`和`volatile`!您无法更改对象,但可以在背后更改. (13认同)
  • @Destructor假设您正在控制LED的状态.写0将其关闭,写1将其打开.如果我需要闪烁LED以传达一些错误状态,但编译器决定优化除最后一个之外的所有写入,因为没有使用任何值,那么LED永远不会闪烁并且我想要的行为没有实现. (5认同)
  • @Destructor:通常的情况是写入硬件设备寄存器. (2认同)

xia*_*ian 27

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

volatile:volatile关键字是一个依赖于实现的修饰符,在声明变量时使用,这会阻止编译器优化这些变量.Volatile应该与变量一起使用,其值可能以意外的方式(即通过中断)发生变化,这可能与编译器可能执行的优化冲突.

资源


Ben*_*igt 22

他们绝对不是一回事.Mutable与const交互.如果你有一个const指针,你通常无法更改成员.Mutable为该规则提供了一个例外.

另一方面,易失性与程序的变化完全无关.这意味着内存可能因编译器无法控制的原因而发生更改,因此编译器必须每次都读取或写入内存地址,并且无法将内容缓存在寄存器中.


Jon*_*ler 17

一种粗略但有效的思维方式是:

  • 编译器知道可变对象何时更改.
  • 编译器无法知道volatile对象何时发生更改.


Kyl*_*utz 11

标记的变量mutable允许在声明的方法中修改它const.

标记的变量volatile告诉编译器每次代码都告诉它必须读/写变量(即它不能优化对变量的访问).


小智 5

我想补充一点,在处理多线程应用程序时,易失性也非常有用,即,您有主线程(main() 所在的位置),并且您生成一个工作线程,当变量“app_running”为 true 时,该线程将继续旋转。main() 控制“app_running”的真假,因此如果没有在“app_running”的声明中添加 volatile 属性,如果编译器优化了辅助线程运行的代码中对“app_running”的访问,main( )可能会将“app_running”更改为 false,但辅助线程将继续运行,因为该值已被缓存。我在 Linux 和 VisualC++ 上使用 gcc 看到了相同的行为。“app_running”声明中的“易失性”属性解决了这个问题。因此,在这种情况下,不会涉及硬件中断或内核来更改此类变量的值。

  • 不!这是一个常见的误解。C++11 和 C11 为此引入了原子 http://stackoverflow.com/questions/8819095/concurrency-atomic-and-volatile-in-c11-memory-model (2认同)