在使用const的任何地方都可以使用volatile吗?

时间:2012-01-21 11:25:48

标签: c++ const volatile

我想知道volatile可以在const可以使用的地方使用volatile dummy_class volatile dummy_class& dummy_class volatile* dummy_class *volatile dummy_class volatile *volatile ,以及每种情况的含义。

const

当涉及volatile时,这些都是不同的情况,相同的语义是否适用于{{1}}?

4 个答案:

答案 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

但是,有一条规则规定您无法将constmutable 合并为:

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

因此,constvolatile可以在相同的位置使用,可能会结合使用。

该部分第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类型。

constvolatile都不能应用于静态成员函数。

答案 2 :(得分:1)

任何变量都可以声明为constvolatile(或两者),但它们具有不同的语义。

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,我不知道这是否已经改变,因为你可以在类定义中初始化成员,我不知道这是否扩展到静态成员。