By Ryui Liu 2011/11/26
C++中const关键字允许你指定一个语义约束即指定这是一个“不能被改动”的对象,而编译器会强制实施这项约束。当你确实不希望某值保持不变时,你就该确实的说出来,这样编译器就可以帮助你确保这个值不被改变。
const可以在class外部修饰global或namespace作用域中的常量,可以修饰文件、函数、或区块作用域中被static声明的对象,可以修饰classes内部的static或non-static成员变量,也可以修饰常量指针、指针常量、指向常量的指针常量;const最有威力的用法还是在函数声明时,可以和函数的返回值,各个参数,函数自身产生关联。
const修饰变量时,如果const关键字出现在星号的左边,表示被指物是常量(没有星号时(即非指针变量)也适用),如果出现在星号的右边,则表示指针自身是常量,如果在星号两边都出现,则被指物和指针两者都是常量。
const int i = 10;
char greeting [] = "hello world";
char greeting2[] = "qu world";
const char *p = greeting;
char const *q = greeting; // p和q都是常量指针
char * const cq = greeeting; // cq为指针常量,不能改变它的指向
*p = "aaaa";// error
P = greeting2; //ok
cq = greeting2; // error
*cq ="aaaaa"; //ok
const char* const pq = greeting; //pq是指向常量的指针常量
STL跌代器iterator 是普通指针,如果在其前面加上const修饰时,则该指针不能被改变,既迭代器不能改变,而const_iterator是一个指向常量的指针。例如:
std::vector<int > vec;
const std::vector<int>::iterator iter = vec.begin();
*vec = 10 ;//ok
++vec; // error
std::vector<int>::const_iterator cIter = vec.begin();
*vec = 10;//error
++vec; //ok
const修饰函数时,可以给参数加上const不希望修改参数的值,也可以给返回值加上const不希望无意中改变返回值。例如:
class aa{.....};
const aa operator*(const aa& a1,const aa& a2);
此处则不希望改变operator *的返回值,假如一个混混沌沌的程序员写出if(a*b = c), 编译器给他错误提示了;如果没有加上const,或许他会抓狂的。
在c++面向对象编程中,常用const来修饰类的成员函数,这样做是为了确认该成员函数可以作用于const对象身上。这样做有两个重要理由:第一、它们使class接口比较容易理解,得知哪个函数可以改动对象内容而哪个函数不可以,例如常见的get/set函数;第二、它们使“操作const对象”成为可能,这对编写高效代码是个关键。
需要提示的是:两个成员函数如果只有常量性不同即一个有const修饰,另一个没有,可以被重载。
const char& operator[](std::size_t position)const {return ...}; //operator [] for const对象
char &operator[] (std::size_t position)(return ...);//operator[] for non-const 对象。
众所周知,我们在const成员函数中不能修改成员变量,但当需要修改时就需要另外一个关键字---mutable.
例如
class MutableTest
{
public:
MutableTest();
~MutableTest();
void Output() const;
int GetOutputTimes() const;
private:
mutable int m_iTimes;
};
MutableTest::MutableTest()
{
m_iTimes = 0;
}
MutableTest::~MutableTest()
{}
void MutableTest::Output() const
{
cout << "Output for test!" << endl;
m_iTimes++;
}
int MutableTest::GetOutputTimes() const
{
return m_iTimes;
}
在这个例子中,将Output函数修饰为const,却希望记录输出的次数,这时就需要改变m_iTimes的值,这个时候就需要mutable关键字来突破const关键字的限制了:m_iTimes在常成员函数中也可以被改变。
总结:const可以被施加于任何作用域内的对象、函数参数、函数返回类型、成员函数本体,将某些东西声明为const可以帮助编译器侦测错误用法。当需要在const的成员函数内部修改成员变量时,可以求助于mutable关键字。