您的位置:首页 > 其它

const、volatile、mutable关键字

2015-08-16 22:39 351 查看
转载自: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关键字[/u]

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也是用来输出的,里面调用了对象lx的Output输出方法,为了防止在函数中调用成员函数修改任何成员变量,所以参数也被const修饰。
假如现在,我们要增添一个功能:计算每个对象的输出次数。假如用来计数的变量是普通的变量的话,那么在const成员函数Output里面是不能修改该变量的值的;而该变量跟对象的状态无关,所以应该为了修改该变量而去掉Output的const属性。这个时候,就该我们的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_iTimes被mutable修饰,那么它就可以突破const的限制,在被const修饰的函数里面也能被修改。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: