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 专用
另请参阅
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈