20 July 2023

C++ 核心指南目录

“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>