const、volatile、mutable关键字

转载自:http://blog.csdn.net/wuliming_sc/article/details/3717017

const关键字

变量宏方面:

const 修饰变量:常量非指针类型,非指针常量类型并没有什么区别

const修饰指针:常量指针:是指针不过指向的是常量可以进行p++操作不能进行*p操作;指针常量:是常量,不过有一个指向它地址的指针,可以进行*p操作,不可以进行p++操作。

用常量代替宏的作用,让代码更加易于调试。

函数方面:

常量函数参数,可以简化代码和允许常量传入函数,因为变量可以赋值给常量,但是常量不能赋值给变量。

函数常量返回值,避免返回值间相互赋值,改变返回值。


类对象方面:

常量对象,常量引用,说明常量和引用是不可以改变的。

常量数据成员,才构造函数初始化列表中给出,保护数据作用,数据不能改变。

常量成员函数,是函数不能修改类数据成员的(如果有mutable修饰的数据成员还是可以修改的)。



volatile关键字

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

当要求使用volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被寄存。例如:

volatile int i=10;

int a = i;

。。。//其他代码,并未明确告诉编译器,对i进行过操作

int b = i;

volatile 指出 i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的汇编代码会重新从i的地址读取数据放在b中。而优化做法是,由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在b中。而不是重新从i里面读(如果是用volatile修饰了那么就会从i中重新读取变量)。这样以来,如果i是一个寄存器变量或者表示一个端口数据就容易出错,所以说volatile可以保证对特殊地址的稳定访问


mutable关键字

mutalbe的中文意思是“可变的,易变的”,constant(既C++中的const)是反义词。在C++中,mutable也是为了突破const的限制而设置的。被mutable修饰的变量(mutable只能由于修饰类的非静态数据成员),将永远处于可变的状态,即使在一个const函数中。

我们知道,假如类的成员函数不会改变对象的状态,那么这个成员函数一般会声明为const。但是,有些时候,我们需要在const的函数里面修改一些跟类状态无关的数据成员,那么这个数据成员就应该被mutalbe来修饰。下面是一个小例子:

class ClxTest

{

 public:

  void Output() const;

};

 

void ClxTest::Output() const

{

 cout << "Output for test!" << endl;

}

 

void OutputTest(const ClxTest& lx)

{

 lx.Output();

}

ClxTest的成员函数Output是用来输出的,不会修改类的状态,所以被声明为const

函数OutputTest也是用来输出的,里面调用了对象lxOutput输出方法,为了防止在函数中调用成员函数修改任何成员变量,所以参数也被const修饰。

假如现在,我们要增添一个功能:计算每个对象的输出次数。假如用来计数的变量是普通的变量的话,那么在const成员函数Output里面是不能修改该变量的值的;而该变量跟对象的状态无关,所以应该为了修改该变量而去掉Outputconst属性。这个时候,就该我们的mutable出场了,只要用mutalbe来修饰这个变量,所有问题就迎刃而解了。下面是修改过的代码:

class ClxTest

{

 public:

  ClxTest();

  ~ClxTest();

 

  void Output() const;

  int GetOutputTimes() const;

 

 private:

  mutable int m_iTimes;

};

 

ClxTest::ClxTest()

{

 m_iTimes = 0;

}

 

ClxTest::~ClxTest()

{}

 

void ClxTest::Output() const

{

 cout << "Output for test!" << endl;

 m_iTimes++;

}

 

int ClxTest::GetOutputTimes() const

{

 return m_iTimes;

}

 

void OutputTest(const ClxTest& lx)

{

 cout << lx.GetOutputTimes() << endl;

 lx.Output();

 cout << lx.GetOutputTimes() << endl;

}

计数器m_iTimesmutable修饰,那么它就可以突破const的限制,在被const修饰的函数里面也能被修改


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值