"volatile"限定符和编译器重新排序

Ale*_*x B 14 c c++ volatile compiler-optimization

编译器无法消除或重新排序对volatile限定变量的读/写.

但是,存在其他变量的情况又volatile如何呢?

场景1

volatile int a;
volatile int b;

a = 1;
b = 2;
a = 3;
b = 4;
Run Code Online (Sandbox Code Playgroud)

编译器可以重新排序第一次和第二次,第三次和第四次分配吗?

情景2

volatile int a;
int b, c;

b = 1;
a = 1;
c = b;
a = 3;
Run Code Online (Sandbox Code Playgroud)

同样的问题,编译器可以重新排序第一个和第二个,或第三个和第四个任务吗?

Ste*_*sop 12

C++标准说(1.9/6):

抽象机器的可观察行为是它对易失性数据的读写顺序以及对库I/O函数的调用.

在方案1中,您建议的任何更改都会更改对易失性数据的写入顺序.

在方案2中,您建议的更改都不会更改序列.所以他们被允许遵循"as-if"规则(1.9/1):

...符合实现需要模拟(仅)抽象机器的可观察行为......

为了说明这种情况已经发生,您需要检查机器代码,使用调试器,或引发未定义或未指定的行为,这些行为的结果是您在实现时碰巧知道的.例如,实现可能会保证同时执行的线程具有相同内存的视图,但这超出了C++标准的范围.因此,虽然标准可能允许特定的代码转换,但是特定的实现可以排除它,理由是它不知道您的代码是否将在多线程程序中运行.

如果您要使用可观察行为来测试重新排序是否已经发生(例如,在上面的代码中打印变量的值),那么当然标准不允许这样做.