一、使用const
对于指针来说,若关键字const出现在星号左边,则表示被指物是常量;若出现在星号右边,表示指针自身是常量;若出现在星号两边,则表示被指物和指针两者都是常量。
STL迭代器以指针为根据塑膜出来,所以迭代器的作用就像个T*指针。声明迭代器为const就像声明指针为const一样(即声明一个T*const指针),表示这个迭代器不得指向不同的东西,但它所指的东西的值可以改动。若希望迭代器所指的东西的值不可改动(即希望STL模拟一个const T*指针),则需要const_iterator:
vector<int> vec;
const std::vector<int>::iterator iter=vec.begin();//iter的作用就像T*const
*iter=10;//正确
//++iter;//错误
std::vector<int>::const_iterator citer=vec.cbegin();//citer的作用就像const T*
//*citer=10;//错误
++citer;//正确
二、令函数返回常量值
令函数返回一个常量值,往往可以降低因客户错误而造成的意外,而又不至于放弃安全性和高效性。
例:
class Rational{
public:
const operator*(const Rational &lhs,const Rational &rhs){}
}
若不像上述代码一样将函数的返回值声明为const,则在用这样的代码时会出现错误:
Rational a,b,c;
(a*b)=c;//在a*b的成果上调用operator=
上述代码有可能是单纯的打字错误,但这样做是错误的。
三、const成员函数
将const实施于成员函数的优点有:
1.它们使class接口比较容易被理解。因为,可以得知哪个函数可以改动对象内容而哪个函数不行。
2. 它们能够使const函数操作const对象。
改善C++程序效率的一个根本办法是以pass by reference-to-const方式传递对象。
(一)const成员函数的重载
注:两个成员函数若只是常量性不同,可以被重载。
例:
class TextBlock{
public:
const char& operator[](std::size_t position) const{return text[position];}
//operator[] for const对象
char& operator[](std::size_t position){return text[position];}
//operator[] for non-const对象
private:
std::string text;
};
TextBlock tb("Hello");
cout<<tb[0];//调用non-const TextBlock::operator[]
const TextBlock ctb("World");
cout<<ctb[0];//调用const TextBlock::operator[]
(二)const成员函数改变成员变量的方法
当一个成员函数被声明为const后,则在其内无法改变成员变量的值,不管这个成员变量是不是常量。
若想在const成员函数中改变非const成员变量的值,可以使用mutable(可变的)。
muable释放掉成员函数对non-const成员变量的限制。
例:
class CTextBlock{
public:
std::size_t length() const
{
textLength=std::strlen(pText);//这样的操作是被允许的
return textLength;
}
private:
char* pText;
mutable std::size_t textLength;//可以在const成员函数内被改变
}
(三)在const和non-const成员函数中避免重复
当代码长度过长时,将这些代码分别放进const和non-const operator[]中,会增加代码的维护成本。可以用一个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]);
//将op[]返回值的const转除,为*this加上const,调用const op[]
}
};
上述代码有两个转型动作,第一次是为*this添加const保证调用的函数是const operator[],第二次是从const operator[]的返回值中移除const。
四、总结
1.将某些东西声明为const可帮助编译器侦测出错误用法。const可被施加于任何作用域内的对象、函数参数、函数返回类型、成员函数本体。
2.当const和non-const成员函数有着实质等价的实现时,令non-const版本调用const版本可避免代码重复。