什么样的优化在C++中"易失"?

gab*_*lin 25 c++ optimization volatile

我正在查找关键字volatile以及它的用途,我得到的答案非常多:

它用于防止编译器优化代码.

有一些示例,例如轮询内存映射硬件时:没有volatile轮询循环将被删除,因为编译器可能会识别出条件值永远不会更改.但由于只有一个例子或两个例子,它让我思考:volatile在避免不必要的优化方面我们还需要使用其他情况吗?条件变量是唯一volatile需要的地方吗?

我认为优化是特定于编译器的,因此未在C++规范中指定.这是否意味着我们必须通过直觉,说嗯,我怀疑如果我没有声明该变量volatile或者是否有任何明确的规则,我的编译器将废除它

sbi*_*sbi 25

基本上,volatile宣布一个值可能会在你的程序背后发生变化.这可以防止编译器缓存该值(在CPU寄存器中),并防止在程序的POV中看起来不必要时访问该值.

触发使用的volatile是当值发生变化时,尽管程序没有写入,并且没有其他内存障碍(如用于多线程程序的互斥锁).


GMa*_*ckG 21

C++程序的可观察行为取决于对volatile变量的读写,以及对输入/输出函数的任何调用.

这需要的是,对volatile变量的所有读写都必须按照它们在代码中出现的顺序发生,并且它们必须发生.(如果编译器违反了其中一条规则,则会破坏as-if规则.)

就这样.当您需要指示读取或写入变量被视为可观察的效果时,可以使用它.(注意,"C++和双重锁定的危险"文章对此有所了解.)


因此,为了回答标题问题,它会阻止任何可能重新排序相对于其他volatile变量的volatile变量评估的优化.

这意味着更改的编译器:

int x = 2;
volatile int y = 5;
x = 5;
y = 7;
Run Code Online (Sandbox Code Playgroud)

int x = 5;
volatile int y = 5;
y = 7;
Run Code Online (Sandbox Code Playgroud)

很好,因为价值x不是可观察行为的一部分(它不易变).什么是不错的是将赋值从5更改为赋值为7,因为写5是一个可观察的效果.


Pot*_*ter 10

条件变量不是哪里volatile需要; 严格来说,它只在设备驱动程序中需要.

volatile保证对对象的读取和写入不会被优化掉,或者相对于另一个进行重新排序volatile.如果您正在忙于循环另一个线程修改的变量,则应该声明它volatile.但是,你不应该忙着循环.由于该语言并非真正为多线程设计,因此不太受支持.例如,编译器可以移动一个写入到循环之前从后-volatile变量,违反了锁.(对于无限旋转,这可能只发生在C++ 0x下.)

当您调用线程库函数时,它充当内存栅栏,编译器将假定所有值都已更改 - 基本上所有内容都是volatile.这可以由任何线程库指定或默认实现,以保持车轮平稳转动.

C++ 0x可能没有这个缺点,因为它引入了正式的多线程语义.我并不熟悉这些更改,但为了向后兼容,它不需要声明之前没有的任何volatile.

  • “局部变量根本不允许是易失性的,尽管有些编译器可能支持它,并且您可以选择通过 volatile * 独占地访问局部变量” -> 我已经在嵌入式系统的等待循环中看到了局部易失性变量等等。您能提供一个标准参考吗?另请注意,如果您有一个“int”对象,但仅通过“int 易失性&”(或通过取消引用“int 易失性*”)来访问它,则这不会被视为易失性读/写,因此编译器可能会优化它。 (2认同)