volatile关键字的作用是什么?在c++中它能解决什么问题?

就我而言,我从来没有明知肚明地需要它。


当前回答

除了按预期使用它,volatile还用于(模板)元编程。它可以用来防止意外重载,因为volatile属性(如const)参与了重载解析。

template <typename T> 
class Foo {
  std::enable_if_t<sizeof(T)==4, void> f(T& t) 
  { std::cout << 1 << t; }
  void f(T volatile& t) 
  { std::cout << 2 << const_cast<T&>(t); }

  void bar() { T t; f(t); }
};

这是合法的;这两个重载都可能是可调用的,并且执行几乎相同的操作。在volatile重载中的强制转换是合法的,因为我们知道bar无论如何都不会通过一个非volatile T。不过,volatile版本严格来说更糟糕,所以如果非volatile f可用,则永远不要在重载分辨率中选择。

注意,代码实际上从不依赖于volatile内存访问。

其他回答

除了volatile关键字用于告诉编译器不要优化对某些变量(可以由线程或中断例程修改)的访问之外,它还可以用于删除一些编译器错误——是的,它可以是——。

例如,我在一个嵌入式平台上工作,编译器对变量的值做出了一些错误的假设。如果代码没有优化,程序可以正常运行。通过优化(这是非常必要的,因为这是一个关键的例程),代码将无法正常工作。唯一的解决方案(虽然不是很正确)是将“错误的”变量声明为volatile。

我想引用Herb Sutter在GotW #95中的一句话,这有助于理解volatile变量的含义:

C++ volatile variables (which have no analog in languages like C# and Java) are always beyond the scope of this and any other article about the memory model and synchronization. That’s because C++ volatile variables aren’t about threads or communication at all and don’t interact with those things. Rather, a C++ volatile variable should be viewed as portal into a different universe beyond the language — a memory location that by definition does not obey the language’s memory model because that memory location is accessed by hardware (e.g., written to by a daughter card), have more than one address, or is otherwise “strange” and beyond the language. So C++ volatile variables are universally an exception to every guideline about synchronization because are always inherently “racy” and unsynchronizable using the normal tools (mutexes, atomics, etc.) and more generally exist outside all normal of the language and compiler including that they generally cannot be optimized by the compiler (because the compiler isn’t allowed to know their semantics; a volatile int vi; may not behave anything like a normal int, and you can’t even assume that code like vi = 5; int read_back = vi; is guaranteed to result in read_back == 5, or that code like int i = vi; int j = vi; that reads vi twice will result in i == j which will not be true if vi is a hardware counter for example).

Dan Saks在《Volatile as a promise》一文中写道:

易失性对象是其值可能自发变化的对象。也就是说,当你声明一个对象为volatile时,你是在告诉编译器这个对象可能会改变状态,即使程序中没有任何语句显示要改变它。”

以下是他关于volatile关键字的三篇文章的链接:

明智地使用挥发剂 准确放置挥发剂 像承诺一样反复无常

为嵌入式开发,我有一个循环,检查可以在中断处理程序中更改的变量。如果没有“volatile”,循环就变成了noop——就编译器所知,变量永远不会改变,所以它优化了检查。

同样的事情也适用于在更传统的环境中可能在不同线程中更改的变量,但在那里我们经常进行同步调用,因此编译器在优化方面没有那么自由。

volatile关键字的目的是防止编译器对可能以编译器无法确定的方式改变的对象应用任何优化。

声明为volatile的对象在优化中被省略,因为它们的值可以被当前代码范围之外的代码随时更改。系统总是从内存位置读取volatile对象的当前值,而不是在请求时将其值保存在临时寄存器中,即使之前的指令从同一对象中请求一个值。

考虑以下情况

1)由中断服务例程在作用域外修改的全局变量。

2)多线程应用程序中的全局变量。

如果不使用volatile限定符,可能会出现以下问题

1)当优化被打开时,代码可能不会像预期的那样工作。

2)当中断被启用和使用时,代码可能不会像预期的那样工作。

Volatile:程序员最好的朋友

https://en.wikipedia.org/wiki/Volatile_ (computer_programming)