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.