volatile (C++)

可用于声明可在程序中由硬件修改的对象的类型限定符。

语法

volatile declarator ;

备注

可以使用 /volatile 编译器开关来修改编译器解释此关键字的方式。

Visual Studio 根据目标体系结构以不同的方式解释 volatile 关键字。 对于 ARM,如果未指定 /volatile 编译器选项,则编译器的执行方式就如同指定了 /volatile:iso 一样。 对于 ARM 之外的体系结构,如果未指定 /volatile 编译器选项,则编译器的执行方式就如同指定了 /volatile:ms 一样;因此,对于 ARM 之外的体系结构,我们强烈建议在处理跨线程共享的内存时,指定 /volatile:iso,并使用显式同步基元和编译器内部函数。

可以使用 volatile 限定符提供对异步过程(如中断处理程序)使用的内存位置的访问权。

在对也具有 __restrict 关键字的变量使用 volatile 时,优先考虑 volatile

如果将 struct 成员标记为 volatile,则 volatile 将传播到整个结构。 如果结构不具有可通过使用一个指令在当前体系结构上复制的长度,则此结构上可能完全丢失 volatile

如果满足下列条件之一,则 volatile 关键字可能对字段不起作用:

  • 可变字段的长度超过可使用一条指令在当前体系结构上复制的最大大小。

  • 最外层包含 struct 的长度 - 或如果它是可能嵌套的 struct 的成员 - 超过可使用一条指令在当前体系结构上复制的最大大小。

尽管处理器不会对不可缓存的内存访问重新排序,但必须将不可缓存的变量标记为 volatile,从而保证此编译器不会对内存访问重新排序。

声明为 volatile 的对象不在某些优化中使用,因为它们的值可以随时更改。 系统在请求易失对象时始终读取该对象的当前值,即使前面的指令要求从同一对象获取值也是如此。 此外,对象的值会立即在赋值时写入。

ISO 一致性

如果熟悉 C# volatile 关键字或熟悉早期版本的 Microsoft C++ 编译器 (MSVC) 中 volatile 的行为,请注意,在指定 /volatile:iso 编译器选项时,C++11 ISO 标准 volatile 关键字是不同的且在 MSVC 中受支持。 (对于 ARM,默认情况下将指定它。) C++11 ISO 标准代码中的 volatile 关键字仅用于硬件访问;请不要将其用于线程间通信。 对于线程间通信,请使用 C++ 标准库中的 std::atomic<T> 等机制。

符合 ISO 的结尾

Microsoft 专用

在使用 /volatile:ms 编译器选项时 - 默认情况下,在面向 ARM 之外的体系结构时 - 编译器会生成额外代码来维护对可变对象的引用之间的排序,还维护对其他全局对象的引用的排序。 具体而言:

  • 对可变对象进行写入(也称为可变编写)具有“发布”语义;也就是说,对指令序列中的可变对象进行写入之前发生的全局或静态对象的引用将在已编译的库中写入可变对象之前发生。

  • 对可变对象进行读取(也称为可变读取)具有“获取”语义;也就是说,对指令序列中的可变对象进行读取之前发生的全局或静态对象的引用将在已编译的库中读取可变对象之前发生。

这使易失性对象可用于多线程应用程序中的内存锁和释放。

注意

当它依赖于在使用 /volatile:ms 编译器选项时提供的增强保证时,代码是不可移植的。

结束 Microsoft 专用

另请参阅

关键字
const
固定和可变指针