直接处理硬件的程序常常包含这样的数据元素,它们的值由程序直接控制之外的过程控制。例如,程序可能包含一个由系统时钟定时更新的变量。当对象的值可能在程序的控制或检测之外被改变时,应该将该对象声明为volatile。关键字volatile告诉编译器不应对这样的对象进行优化。
用法类似const,我们可以按顶层const、底层const去理解volatile。
volatile int display_register; // 该int值可能发生改变
volatile Task *curr_task; // curr_task指向一个volatile对象
volatile int iax[max_size]; // iax的每个元素都是volatile
volatile Screen bitmapBuf; // bitmapBuf的每个成员都是volatile
volatile int v; // v是一个volatile int
int *volatile vip; // vip是一个volatile指针,它指向int
volatile int *ivp; // ivp是一个指针,它指向一个volatile int
volatile int *volatile vivp; // vivp是一个volatile指针,它指向一个volatile int
int *ip = &v; // 错误:必须使用指向volatile的指针
ivp = &v; // 正确:ivp是一个指向volatile的指针
vivp = &v; // 正确:vivp是一个指向volatile的volatile指针
合成的拷贝对volatile对象无效,这是和const的区别。不能使用合成的拷贝/移动构造函数及赋值运算符初始化volatile对象或从volatile对象赋值。
如果一个类希望拷贝、移动或赋值它的volatile对象,则该类必须自定义拷贝或移动操作。
class Foo {
public:
Foo(const volatile Foo&); //从一个volatile对象进行拷贝
// 将一个volatile对象赋值给一个非volatile对象
Foo& operator=(volatile const Foo&);
// 将一个volatile对象赋值给一个volatile对象
Foo& operator=(volatile const Foo&) volatile;
// Foo类的剩余部分
}