1. const可被施加于任何作用域内的对象,函数参数,函数返回类型,成员函数本体.用const修饰指针,如果const出现在*之前,表明指针不能更改所指向的对象的内容,如果const出现在*之后,表明指针只能指向同一块内存.另外int const*p和const int*p含义相同.如果对象成员有普通指针,那么构造该类的一个const对象时,const修饰使得该指针只能指向同一块内存,但指针指向的内容可以改变.
2. 将某些东西声明为const可以帮助编译器侦测出错误用法.
3. 编译器强制实行bitwise constness(又称physical constness,物理上的常量性,即成员函数不更改对象的任何一个bit时才可以说是const),例如:
class TextBlock{ public: ... char& operator [](std::size_t position) const{ return pText[position]; } private: char* pText; }
编译器认定它是bitwise constness的,但是它却允许以下代码的存在:
const CTxetBlock cctb("Hello"); char* pc=&cctb[0]; *pc=‘J‘;
这是由于只有pText是cctb的一部分,其指向的内存并不属于cctb
程序员编写程序时应该使用conceptual constness(概念上的常量性或logical constness,逻辑上的常量性,即一个const成员函数可以处理它所修改的对象的某些bits,但只有在客户端侦测不出的情况下才得如此),例如对于某些特殊类,其中的某些成员的值注定是要改变的,因此可以用mutual关键字修饰,从而实现即使对象被设定为const,其特定成员的值仍然可以改变的效果.此时该类符合conceptual constness而不符合bitwise constness.
4. 如果参数是引用,可以基于参数是否为const实现函数重载(也可以基于指针是否为const实现函数重载),特殊的,对于成员函数,因为它存在一个隐含的this指针参数,因而可以基于函数是否为const实现重载.
5. 当const和non-const成员函数拥有重复的实现时,令non-const版本调用const版本可避免代码重复,例如对于以下实现:
class TextBlock{ public: ... const char& operator[](std::position) const{ ... return text[position]; } char& operator[](std::position) { ... return text[position]; } private: std::string text; }
通过令non-const版本调用const版本如下:
class TextBlock{ public: ... const char& operator[](std::size_t position) const{ ... return text[position]; } char operator[](std::size_t position){ return const_cast<char&>( static_cast<const TextBlock&>(*this)[position]); } ... };
可以看出,经过了两次类型转换,第一次通过static_cast将*this转为const TextBlock&以确保调用的是operator[]的const版本,否则会调用非const版本导致递归调用造成栈溢出;第二次通过const_cast去掉const版本的opsrator[]返回的const char&的const特性以与函数的返回类型相匹配.
注意,不能用const版本调用non-const版本,因为non-const版本极有可能改变对象的值,这与const版本的const特性相矛盾.
6.注:对于const_cast的行为之前存在一些误解,对于以下代码:
#include<iostream> using std::cout; using std::endl; int main(){ const int a = 5; int& rta = const_cast < int&>(a) ; rta = 6; cout << "a: " << a << " rtr: " << rta << endl; cout << "&a: " << &a << " &rta: " << &rta; system("pause"); return 0; }
输出结果如下:
可见虽然const_cast表面上改变了变量的const性质,但a的值实际上还是没有改变(编译器仍然背着我们干了不少事),所以const_cast的实际用途并不是改变const对象的值,而是"暂时"去除对象的const属性使其可以作为参数传入非const函数,企图通过const_cast改变const对象的值可能会导致未预料的结果.因此个人认为5中的第二段代码(出自Effective C++ “条款3 尽可能用const”)存在一些错误,如有错误欢迎批评指正!