Effective C++ 条款03:尽可能使用const
const告诉编译器某个值不能是变化的。
修饰指针
const修饰指针的时候,只区分在*前还是*后。在前面表示指针常量,其指向的值无法通过这个指针改变;在后面表示常量指针,表示这个指针无法指向别的对象,但可以通过该指针修改该对象的值。
int a = 10;
const int *p1 = &a;
int const *p2 = &a;
int * const p3 = &a;
const int * const p4 = &a;
int const * const p5 = &a;
// equals to
const int *p1 = &a;
int* const p2 = &a;
const int * const p3 = &a;
下面以STL中的迭代器作为说明。STL中有两种迭代器,普通的iterator和const_iterator。const_iterator类似于const int *p 这种指针常量。即不能通过const_iterator修改容器内成员的值。
std::vector<int> vec;
std::vector<int>::const_iterator citer = vec.begin();
*citer = 10; // wrong
citer++; // right
相反,如果我们希望迭代器固定指向某一个值,就需要在它前面加上const
const std::vector<int>::iterator iter = vec.begin();
iter++; // wrong
*iter = 10 // right
修饰函数
函数返回值
令函数返回一个常量可以避免某些意外。例如重载*时返回const值。
class Rational;
const Rational operator*(const Rational& lhs, const Rational& rhs);
我们定义了一个Rational类,重载了乘法操作符。如果我们将返回值定义为const那么这种写法编译器就会报错
Rational a, b;
// assigned value for a and b
...
// error
a * b = c;
// but this is our attention
a * b == c;
这种写法虽然没有任何意义,但是可能我们本来是想判断a * b后是不是等于c的。这样编译器就可以帮助我们纠正这个错误。
成员函数
const对象只能调用const成员函数。
设置一个const的成员函数,再重载一个non-const的版本。这样const对象就会调用const 的版本,而non-const的对象就会调用non-const的版本。
看个例子
class TextBlock {
public:
TextBlock(): text("null"){}
const char& operator[](size_t position) const
{return text[position];}
char& operator[](size_t position)
{return text[position];}
private:
string text;
};
int main(){
TextBlock a;
const TextBlock const_a;
a[0] = 'a'; // valid
const_a[0] = 'b'; // invalid
}
这里我们定义了个TextBlock类,写了两个版本的[]重载。很显然,如果一个TextBlock是const的,那么自然取值以后我们也不希望它被修改,因此const版本的操作符重载需要返回一个const char&
此外,顺带一提的是在non-const版本中,返回值也必须是char&。因为只有返回了引用,我们的修改才能真正作用到类中的数据上。而且如果你不写引用编译器会报错。
后面还有一部分内容下次再补好了= =

浙公网安备 33010602011771号