CppCoreGuidelines CP.200 只用 volatile 访问非 C++ 的内存
20 July 2023
“Use volatile only to talk to non-C++ memory”
理由
volatile
是用来访问非 C++ 的对象,或者用来访问不遵循 C++ 内存模型的硬件数据的。
例子
const volatile long clock;
这里描述的是一个一直被时钟电路更新的寄存器。时钟是转瞬即逝的数据,因为它的改变不需要 C++ 程序的任何操作。比如,读取时钟两次会得到两个不同的值。所有优化器最好不要把两次读取优化成一次:
long t1 = clock; // ... no use of clock here ... long t2 = clock;
时钟是常量,程序不该改写时钟数据。
注意
除非你编写代码直接操作底层硬件。最好避免 volatile
这种深奥的功能。
例子
一般 C++ 代码从别的语言或硬件接收到 volatile
内存:
int volatile* vi = get_hardware_memory_location(); // note: we get a pointer to someone else's memory here // volatile says "treat this with extra respect"
有时候,C++ 代码分配 volatile
内存,通过指针共享给其他语言或硬件。
static volatile long vl; please_use_this(&vl); // escape a reference to this to "elsewhere" (not C++)
坏例子
volatile
的局部变量肯定有问题。如果它是短暂的转瞬即逝的,怎么共享给其他语言和硬件?这个道理同样适用于成员变量:
void f() { volatile int i = 0; // bad, volatile local variable // etc. } class My_type { volatile int i = 0; // suspicious, volatile member variable // etc. };
注意不像其他语言,在 C++ 中 volatile
没有同步的作用。
强化
- 标记
volatile T
局部的或成员变量,大多数情况,你是想要用到atomic<T>