Effective C++第三条款:尽可能使用const
简介:
关键字const多才多艺。你可以用它在classes外部修饰global或者namespace作用域中的常量,或者修饰文件、函数或区块作用域中被声明为static的对象。
1 基础用法:
1.1 修饰变量
如果关键字const出现在星号左边,表示被指物是常量,如果出现在星号右边,那么表示指针自身是常量,如果出现在星号两边,表示被指物和指针都是常量。
char greeting[] = "Hello";
char * p = greetig; //non-const pointer, non-const data
const char * p = greetig; //non-const pointer, const data
char * const p = greetig; //const pointer, non-const data
const char * const p = greetig; //const pointer, const data
1.2 STL迭代器
STL迭代器系以指针为根据塑模出来,所以迭代器的作用就像T*指针。
const std::vector<int>::iterator iter = vec.begin();
*iter = 10; //没问题,改变了iter所指物
++iter;//错误,iter是const
const std::vector<int>::const_iterator citer = vec.begin();
*citer = 10; //错误,cIter是const
++citer;//没问题,改变citer
需要注意的点:
class Solution
{
private:
static int num = 5;//错误,因为类内static初始化变量必须为const
static const int num2 = 5.0;//正确
static const float num3 = 5.0;//错误,因为类内static初始化变量必须为int bool 或者char
static const float num4;//正确,只声明,不定义
public:
int get(){ return (int)num2; };
};
const float Solution::num4 = 5;//非int型const static 数据得在实现文件中定义
2 进阶用法:
2.1 修饰函数
const最具威力的用法是面对函数声明时的应用。在一个函数声明式内,const可以和函数返回值、各参数、函数自身(如果是成员函数)产生关联。
令函数返回一个常量值,往往可以降低因代码书写错误等造成的意外,而又不至于放弃安全性和高效性。举个例子:
class Rational{...};//class Rational定义
const Rational operator *{const Rational & lhs, const Rational & rhs};
也许你对这个声明不免斜着眼睛说,为什么返回一个const对象?因为如果不这这么多,那么可能写出这样的代码:
Rational a,b ,c;
(a*b) = c;//在a*b的成果上调用operator=
或者这样:
if(a*c=c)//其实是想比较
2.2 tips
可能你也一样,冷漠了一个事实:两个成员函数如果只是常量性(constness)不同,就可以重载。
2.3 类中函数后面添加const的意思是:该函数不改变类中的成员,例如:
class CTextBlock {
public:
...
char& operator[](int pos) const//不改变类中变量
{return pText[pos]}
char * pText;
};
2.4 mutable关键字
有时候需要在const更改类中成员变量,又不想去掉const关键字,那么就可以使用mutable关键字。
class cTextBlock {
public:
int length()const;
private:
mutable int size;
}
2.5 转型(casting)
有的时候,const版本和非const版本的函数都需要实现,那么,两个函数内,基本操作相同,这样代码冗余较多,例子如下:
class Solution
{
private:
char * pText;
public:
const char & operator[] (int pos)const//const版本
{
//边界检测
//记录日志
//检验数据完整性
return pText[pos];
};
char & operator[] (int pos)//[]操作符非const版本
{
//边界检测
//记录日志
//检验数据完整性
return pText[pos];
}
};
为了避免这种情况,可以通过如下方法:
class Solution
{
private:
char * pText;
public:
const char & operator[] (int pos)const//const版本
{
//边界检测
//记录日志
//检验数据完整性
return pText[pos];
};
char & operator[] (int pos)//[]操作符非const版本
{
//使用static_cast将this转化成const
//之后再把结果转化成非const
return const_cast<char &>(
static_cast<const Solution&>(*this)[pos]
);
}
};