const允许你指定一个语义约束,而编译器会强制实施这项约束,即它允许你告诉编译器和其它程序员某值应该保持不变。
一、修饰指针
请看下面一段神码:
char greeting[] = "hello";
char* p = greeting; //non-const pointer, non-const data
const char* p = greeting; //non-const pointer, const data
char* const p = greeting; //const pointer, non-const data
const char * const p = greeting; //const pointer, const data
是不是有点头晕
?记住口诀就好:如果关键字const出现在星号左边,表示被指物是常量;如果出现在星号右边,表示指针自身是常量;如果出现在星号两边,表示被指物和指针两者都是常量。需要注意的是:const带来的效果与类型(如上面的char)的位置无关,只与星号位置有关。
二、修饰函数
在一个函数声明中,const可以修饰函数返回值、各参数、函数自身(如果是成员函数)。
1、函数返回值
令函数返回一个常量值,可以降低因调用者错误而造成的意外,而又不至于放弃安全性和高效性,比如:
class Rational {...};
const Rational operator* (const Rational& lhs, const Rational& rhs);
这样做的好处就是防止下面的情况发生:
Rational a, b, c;
...
(a * b) = c; //在a*b的结果上调用operator=
if (a*b = c) //由于打字错误导致比较==变成了赋值,以至于条件永远成立
2、函数参数
const修饰函数参数亦如上例,为了保证输入参数不被函数内部逻辑修改导致错误,这个不必解释,没什么神奇的
。
3、函数自身(成员函数)
const修饰成员函数的目的是保证该函数不能修改成员变量的值,比如:
class CTextBlock {
public:
...
std:size_t length() const;
private:
char* pText;
std:size_t textLength; //最近一次计算的文本区块长度
bool lengthIsValid; //目前长度是否有效
};
std:size_t CTextBlock::length() const
{
if (!lengthIsValid) {
textLength = std::strlen(pText); //错误,在const成员函数中不能赋值给textLength
lengthIsValid = true; //和lengthIsValid
}
return textLength;
}
这点在STL中也是家常便饭,比如:size()、empty()等函数都是const修饰的。
如果有在const修饰的成员函数中改变成员变量值得需求怎么办?可以用mutable修饰non-static成员变量以打破这个约束,比如:
class CTextBlock {
public:
...
std:size_t length() const;
private:
char* pText;
mutable std:size_t textLength; //这些成员变量可能总是会被更改,
mutable bool lengthIsValid; //即使在const成员函数内。
};
std:size_t CTextBlock::length() const
{
if (!lengthIsValid) {
textLength = std::strlen(pText); //OK
lengthIsValid = true; //OK
}
return textLength;
}
阅读(461) | 评论(0) | 转发(0) |