关键字const
用来定义常量,常量声明语句的形式为:
const 数据类型说明 常量名 = 常量值;
数据类型说明 const 常量名 = 常量值;
//例如,声明圆周率PI为一个const,注意,声明为const的变量一定要赋予初值
const float PI = 3.141596;
const与指针
当const
与指针结合起来使用的时候,我们经常都会被搞得晕头转向,常量指针,指针常量,究竟是指针不变,还是指向的内容不变,下面看两个例子:
const char* p = "Hello World"; //常量指针,指向常量的指针
char* const p = "Hello World"; //指针常量,指针本身指向的地址不能够改变
这里可以通过下面这条准则来进行记忆:
如果关键字const出现在星号左边,表示被指示物是常量,如果出现在星号右边,做表示指针自身是常量,如果出现在星号的两边,则表示被指物两者都是常量。
const与STL
STL的迭代器就像是一个T*
的指针,T* const
表示的是指针的位置不能改变,但是其指向的内容可以改变,通过const_iterator
来模拟const T*
,表示指针可以改变,指向的内容不能改变:
std:vector<int> vec;
const std::vector<int>::iterator iter = vec.begin(); //iter的作用相当于是T* const
iter = 10; //没问题,更改iter所指向的值
++iter; //错误,
std::vector<int>::const_iterator cIter = vec.begin(); //相当于是const T*
*cIter = 10; //错误,常量指针无法修改指向的值
cIter++; //没问题
在真实程序中,大多数const的用法是:passed by pointer-to-const 或 passed by reference-to-const
当成员函数是const
的时候,有两个流行的概念:
- Bitwise const:成员函数只有在不改变任何成员变量时才可以说是const
- Logical const:一个const成员函数可以修改它所处理的对象内的某些bits,但只有在客户端检测不出来的情况下才得如此
在某些情况下,可以用logical const,但是编译器不同意,因为它仍然坚持bitwise const,这个时候可以利用C++的一个与const
相关的摆动场:mutable
(可变性),mutable
释放掉non-static
成员变量的bitwise constness约束:
class CTextBlock {
public:
std::size_t length() const;
private:
mutable std::size_t textLength;
mutable bool lengthIsVaild;
};
std::size_t CTextBlock::length() const {
if(!lengthIsVaild) {
textLength = std::strlen(pText);
lengthIsVaild = true;
}
return textLength;
}
常量性转除(casting away constness)
为了避免冗余,可以使用non-const operator[]
调用其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&> { //将op[]返回值的const转除
static_cast<const TextBlock&>(*this) //为*this加上const,调用const op[]
[position]
};
}
};
在这里,首先将*this
从其原始类型TextBlock&
转型为const TextBlock&
,添加了const
,接下来再使用const_cast
去除掉const
。
但是const
成员函数调用non-const
成员函数”是一种错误的行为,因为在约定不改变const
成员函数里面有non-const
,违背了logical const的准则,如果非要这样做的话,可以使用const_cast
去掉*this
身上的const
性质
请记住
- 将某些东西声明为
const
可帮助编译器侦测出错误用法,const可被施加于任何作用域内的对象、函数参数、函数返回类型、成员函数本体。 - 编译器强制实施bitwise constness,但你编写程序时应该使用“概念上的常量性”(conceptual constness)
- 当
const
和non-const
成员函数有着实质等价的实现时,令non-const
版本调用const
版本可避免代码重复