文章目录
指针常量和常量指针的分辨(从右往左读法)。
const在函数中的使用(函数返回类型、函数参数)。
令函数返回一个常量值,往往可以降低因客户错误而造成的以外,而又不至于放弃安全性和高效性。
const成员函数——49
将const实施于成员函数的目的, 是为了确认该成员函数可作用于const对象身上。这一类成员函数之所以重要,基于两个理由。第一,它们使class接口比较容易被理解。第二,它们使“操作const对象”成为可能。这对编写高效代码是个关键,因为如条款20所言,改善C++程序效率的一个根本方法是以通过引用常量(pass by reference-to-const)方式传递对象,而此技术可行的前提是,我们有const成员函数用来处理取得(并经修饰而成)的const对象。
bitwise constness和logical constness——51
bitwise const阵营的人相信,成员函数只有在不更改对象之任何成员变量(static除外)时才可以说是const。也就是说它不更改对象内的任何一个bit。这也是C++对常量性(constness)的定义。
但是有时情况并非如此,如下所示,TextBlock类中有一个所谓的const成员函数:
class CTextBlock{
public:
...
char& operator[](std::size_t position) const{
return pText[position];
}
private:
char* pText;
};
上述class不适当地将其operator[]声明为const成员函数,而该函数却返回一个reference指向对象内部值。因为,operator[]实现代码并不更改pText,所以编译器认为是对的。接下来会有什么后果:
const CTextBlock cctb("Hello");
char* pc=&cctb[0];
*pc='J';
上述代码没有任何错误,但是改变了这个对象的值,最终cctb保存的值变成"Jello"。
由此产生了logical constness拥护者,他们认为一个const成员函数可以修改它所处理的对象内的某些bits,但只有在客户端侦测不出的情况下才得如此。
mutable的用法——52
我们看下面一段代码:
class CTextBlock{
public:
...
std::size_t length() const;
private:
char* pText;
std::szie_t textLength; //最近一次计算的文本区块长度
bool lengthIsValid; //目前的长度是否有效
};
std::size_t CTextBlock::length() const{
if(!lengthIsValid){
textLength=std::strlen(pText); //错误
lengthIsValid=true; //error!
}
return textLength;
}
上述代码中的length函数不能通过编译,因为修改了textLength和lengthIsValid数据,而这个函数有事const。如果想被修改,可利用一个与const相关的摆动场:mutable(可变的)。mutable释放掉non-static成员变量的bitwise constness约束:
class CTextBlock{
public:
...
std::size_t length() const;
private:
char* pText;
mutable std::szie_t textLength;
mutable bool lengthIsValid;
};
std::size_t CTextBlock::length() const{
if(!lengthIsValid){
textLength=std::strlen(pText); //ok
lengthIsValid=true; //ok
}
return textLength;
}
在const和non-const成员函数中避免重复——53
这部分主要讲non-const成员函数使用const_cast和static_cast来调用const成员函数,使避免两个函数写太多重复的操作。
但经验告诉我们,这种强制转换类型并不推荐。
总结——56
(1)将某些东西声明为const可帮助编译器侦测出错误用法。const可被施加于任何作用域内的对象、函数参数、函数返回类型、成员函数本体。
(2)编译器强制实施bitwise constness,但你编写程序时应该使用“概念上的常量性”(consceptual constness)。
(3)当const和non-const成员函数有着实质等价的实现时,令non-const版本调用const版本可避免代码重复。