const、 volatile 和mutable

来源:互联网 发布:c语言选择题题库 编辑:程序博客网 时间:2024/06/05 16:09

const, volatile mutableC/C++中的三种类型限制付。三者具有不同的优点,不同的用途。

下面就三者在不同方面的应用进行一个总结。

一、const:在最初的C语言中const用来修饰变量和指针以及函数参数,但在C++const的用途进一步被拓展。const更确切的解释应该是read only

1const 修饰变量:

一般有两种写法:const type var; type const var;两者的意义相同。

但对于指针类型变量const有三种不同的意义:

const type *pvar;/ int const * pvar; 指向常量的指针。

type * const pvar;指针常量,pvar是不可改变的。

const type * constpvar; 指针和其指向的内容均不可改变。

2const 修饰函数参数

const修饰函数参数一般表示函数体中不能修改函数参数的值。

void func(consttype var); // 无意义,const对值传递没有意义;

void func(type *const pvar);//无意义,函数参数为指针常量,是对指针的值传递,因此也没有意义。

void func(consttype *pvar); // 可以,指针所指内容不能改变

void func(consttype & rvar);// 可以,引用参数内容不能改变

3const修饰类对象/对象指针/对象引用

const修饰类对象/对象指针/对象引用,表示类中的任何内容都不能改变。且被const修饰的对象不能调用类中的非const函数。

4const修饰成员数据

类的const成员数据不能在类中进行初始化,必须利用初始化列表进行初始化,不同类的const数据成员可以不同。如果必须要在类中初始化数组时,可以利用enum类型变量。如:

 

class example{public:example() {}~example(){}private:enum{size_a = 100, size_b =200}; //此时不能用const int size_a //= 100 和 const int size_b =200 代替int arr_a[size_a];int arr_b[size_b];};

 

 

5const 修饰成员函数的返回值

1)   这种情况一般只会发生在运算符重载中,在一般的成员函数很少会用到,因为这样做了之后会规定返回的对象属性为const,那么该对象就只能调用类中的公共的数据成员和const函数。

2)   返回const type *指针,表示指针指向的内容不能被改变,且该返回值只能赋给const type*的指针。

3)   返回const type &引用,这种情况比较少见。返回值采用引用传递的情况一般只出现赋值函数中,目的为了实现链式表达式。

constdefine的区别

1). 编译器处理方式不同

      define是在预处理阶段展开

      const是在编译阶段进行处理

2). 类型和安全检查不同

      define没有类型和安全检查

      const具有类型和安全检查

3). 存储方式不同

      define定义的宏变量在内存中有若干个拷贝,在预编译阶段执行宏展开(直接的替换)。

      const定的变量在内存中只有一份拷贝(因为它是全局的只读变量,存储在静态区)。

二、volatile关键字

volatile本意是“易变的”,其是一种类型修饰符,用它声明的变量表示可以被某些编译器位置的因素改变,比如操作系统,硬件,或其它线程等。遇到这个关键字声明的变量,编译器不会对访问该变量的代码进行优化,从而提供对特定地址的稳定访问。

volatile应用的例子:

1). 并行设备的硬件寄存器(如状态寄存器)

2). 一个中断服务子程序中会访问到的非自动变量(全局变量和静态变量)

3).多线程应用中被多个任务共享的变量

更进步的有关volatile的问题:

1).一个参数既可以是const有可以是volatile吗?为什么?

可以,举个例子:状态寄存器,它是volatile因为它是可能被外界改变的,但它同时也是const的因为它不希望被程序改变。

2).一个指针可以是volatile的吗?

可以,但是这类的事情不常见,比如一个中断服务子程序修改一个纸箱buffer的指针。

3).判断下面程序是否有错误:

int square(volatile  int *ptr){return *ptr * *ptr;}


 

该函数的目的是返回*ptr的平方,但是由于声明了*ptrvolatile的,因此编译器会将其解释为:

int square(volatile int *ptr){int a = *ptr;int b = *ptr;return a*b;} // 这里a和b的值可能不同


 

正确的书写方法应该是

int square(volatile int *ptr){int a = *ptr;return a*a;}

三、 mutable

mutable的意思是“可变的,易变的”,其与const是反义词。它是用来突破const的限制的。比如一个类的const成员函数是不能修改类的状态的,但是如果我们需要修改一些与类的状态无关的数据成员的时候,我们可以将该数据成员声明为mutable