我想知道volatile
可以在const
可以使用的地方使用volatile dummy_class
volatile dummy_class&
dummy_class volatile*
dummy_class *volatile
dummy_class volatile *volatile
,以及每种情况的含义。
const
当涉及volatile
时,这些都是不同的情况,相同的语义是否适用于{{1}}?
答案 0 :(得分:6)
几乎。两者都是 cv-qualifiers ,几乎可以在其他地方使用。它们出现在C ++语法中的唯一地方是:
CV-限定符:
const
volatile
其余的语法将它们引用为 cv-qualifier 。
请注意,您没有提及可以使用 cv-qualifiers 的地方是:
struct X {
void f() const;
void g() volatile;
void h() const volatile;
};
有关后者的使用,请参阅http://drdobbs.com/cpp/184403766。
但是,有一条规则规定您无法将const
和mutable
合并为:
stuct X {
mutable const int x; // error
mutable volatile int y; // valid
};
标准中的相关位置是[dcl.stc]:
mutable说明符只能应用于类数据成员的名称(9.2),不能应用于声明为const或static的名称[...]
答案 1 :(得分:2)
这是来自C ++ 11 draft n3290的第3.9.3节 CV-qualifiers :
3.9.1和3.9.2中提到的类型是cv不合格类型。 每个类型,这是一个cv不合格的完整版 或者不完整的对象类型或者是无效的(3.9)有三个相应的类型的cv限定版本:a const限定版本,volatile限定版本和const-volatile限定版本。对象一词 type(1.8)包括创建对象时指定的cv限定符。 const说明符的存在 在decl-specifier-seq中声明一个const限定对象类型的对象;这样的对象称为const对象。 在decl-specifier-seq中存在volatile说明符声明了一个volatile限定对象类型的对象; 这样的对象称为volatile对象。在decl-specifier-seq中存在两个cv限定符声明了一个 const-volatile-qualified对象类型的对象;这样的对象称为const volatile对象。 cv合格或 cv-非限定版本的类型是不同的类型;但是,它们应具有相同的表示形式 对齐要求(3.9).51
因此,const
和volatile
可以在相同的位置使用,可能会结合使用。
该部分第3段指出它们如何适用于类对象:
const限定类对象的每个非静态,非可变非引用数据成员都是const-quali- fied,volatile限定类对象的每个非静态非引用数据成员都是volatile限定的 类似于const-volatile类的成员。有关具有的功能类型,请参见8.3.5和9.3.2 CV-限定符。
但这很合乎逻辑。
volatile
- 符合条件的对象对 as-if 规则有更严格的要求,即:
严格按照抽象机的规则评估对volatile对象的访问。
波动率以与const
相同的方式附加到对象:
dummy_class volatile* // non-volatile pointer to volatile object
dummy_class *volatile // volatile pointer to non-volatile object
dummy_class volatile *volatile // volatile pointer to volatile object
对于非静态成员函数(第9.3.1节):
非静态成员函数可以声明为const,volatile或const volatile。 这些cv限定符 影响this指针的类型(9.3.2)。它们还影响成员函数的函数类型(8.3.5); 一个成员函数声明const是一个const成员函数,一个成员函数声明volatile是 一个volatile成员函数和一个声明为const的成员函数volatile是一个const volatile成员 功能
因此,像const-ness这样的波动性适用于函数内的this
类型。
const
和volatile
都不能应用于静态成员函数。
答案 2 :(得分:1)
任何变量都可以声明为const
或volatile
(或两者),但它们具有不同的语义。
const
关键字表示变量是常量。 volatile
关键字表示即使您未向其指定任何内容,变量的内容也可能会更改。
例如,如果你有这段代码
int a = ...;
int b = ...;
int sum1 = (a + b) * 2;
int sum2 = (a + b) + 16;
并在编译器上启用优化,编译器可以将之前的代码优化为:
int a = ...;
int b = ...;
int temp = a + b;
int sum1 = temp * 2;
int sum2 = temp + 16;
发生此优化是因为编译器假定在计算sum1和sum2时a和b的值不会改变,因此a + b不会改变。如果将a或b声明为volatile
,则此假设被否定,这意味着编译器将生成每次计算+ b的代码,而不是将其存储在临时位置。这是因为通过声明a或b volatile
表示a或b(以及因此a + b)可能在执行两个语句之间发生了变化。
尽管volatile
似乎是一个无用的关键字,但它在多线程应用程序和进行内存映射I / O(即使用系统内存与硬件通信)时有用。例如,在GameBoy Advance中,必须读取特定的存储位置以确定一次按下哪些键。如果将指向特定内存位置的指针声明为volatile,则始终保证每次都会从内存中读取该特定数据。
答案 3 :(得分:1)
在C ++ 2003中,我认为你无法定义一个类的static int volatile
成员,而你可以使用static int const
成员:后者成为一个常量表达式,只要你不这样做需要一个地址或对象的参考,你会没事的。对于C ++ 2011,我不知道这是否已经改变,因为你可以在类定义中初始化成员,我不知道这是否扩展到静态成员。