条款03:尽可能使用const
Use const whenever possible.
const允许你告诉编译器和其他程序员某值应该保持不变。
如果关键字const出现在星号左边,表示被指物是常量;如果出现在星号右边,表示指针自身是常量;如果出现在星号两边,表示被指物和指针两者都是常量。
1. char greeting[] = "Hello";
2. char* p = greeting; //non-const pointer, non-const data
3. const char* p = greeting; //non-const pointer, const data
4. char* const p = greeting; //const pointer, non-const data
5. const char* const p = greeting; //const pointer, const data
如果被指物是常量,既可以关键字const写在类型之前,又可以把它写在类型之后、星号之前。两种写法的意义等价:
1. void f1(const Widget* pw); //f1获得一个指针,指向一个常量Widget对象..
2. void f2(Widget const * pw); //f2也是
STL迭代器系以指针为底层塑模出来,所以迭代器的作用就像个T*指针。声明迭代器为const就像声明指针为const一样(即声明一个T* const 指针),表示这个迭代器不得指向不同的东西,但它所指的东西的值是可以改动的。如果希望迭代器所指的东西(数据)不可被改动(即希望STL模拟一个const T* 指针),则用const_iterator:
1. std::vector
2. ...
3. const std::vector
4. *iter = 10; //没问题,改变iter所指物
5. ++iter; //错误!iter是const
6. std::vector
7. *cIter = 10; //错误! *cIter是const
8. ++cIter; //没问题,改变cIter。
令函数返回一个常量值,往往可以降低因客户错误而造成的意外,而又不至于放弃安全性和高效性。
1. class Rational { ... };
2. const Rational operator* (const Rational& lhs,const Rational& rhs);
为什么返回一个const对象?原因是如果不这样客户就能实现这样的行为:
1. Rational a, b, c;
2. ...
3. (a * b) = c; //在a * b的成果上调用operator=
如果a和b都是内置类型,这样的代码直截了当就是不合法。而一个"良好的用户自定义类型"的特征是它们避免无端地与内置类型不兼容。将operator* 的回传值声明为const可以预防那个荒唐的赋值动作。
const成员函数
将const实施于成员函数的目的,是为了确认该成员函数可作用于const对象身上。这类成员函数可以得知哪个函数可以改动对象内容而哪个函数不行,很是重要。
两个成员函数如果只是常量性不同,可以被重载。这实在是一个重要的C++特性(前几天的面试刚碰到过):
1. class TextBlock {
2. public:
3. ...
4. const char& operator[](std::size_t position) const
5. { return text[position]; } // operator[] for const对象.
6. char& operator[](std::size_t position)
7. { return text[position]; } // operator[] for non-const对象.
8. private:
9. std::string text;
10. };
11.
12. TextBlock tb("Hello");
13. std::cout << tb[0]; //调用non-const TextBlock::operator[]
14. const TextBlock ctb("World");
15. std::cout << ctb[0]; //调用const TextBlock::operator[]
只要重载operator[]并对不同的版本给予不同的返回类型,就可以令const和non-const TextBlocks获得不同的处理:
1. std::cout << tb[0];//没问题 - 读一个non-const TextBlock
2. tb[0] = 'x'; //没问题 - 写一个non-const TextBlock
3. std::cout << ctb[0];//没问题 - 读一个const TextBlock
4. ctb[0] = 'x'; //错误! - 写一个const TextBlock
上述错误只因operator[] 的返回类型以致,至于operator[] 调用动作自身没问题。
请注意,non-const operator[] 的返回类型是个reference tochar,不是char。如果operator[]只是返回一个char,下面这样的句子就无法通过编译:
1. tb[0] = 'x';
返回类型是内置类型的函数,改动函数返回值不合法。纵使合法,C++以值传递意味被改动的其实是tb.text[0]的一个副本,不是tb.text[0]自身。
l 将某些东西声明为const可帮助编译器侦测出错误用法。const可被施加于任何作用域内的对象、函数参数、函数返回类型、成员函数本体。
成员函数如果是const意味什么?
bitwise const:成员函数只有在不更改对象之任何成员变量(static除外)时才可以说是const,也就是说它不更改对象内的任何一个bit。bitwise constness正是C++ 对常量性的定义,因此const成员函数不可以更改对象内任何non-static成员变量。
不幸的是许多成员函数虽然不十足具备const性质却能通过bitwise测试:
1. class CTextBlock {
2. public:
3. ...
4. char& operator[](std::size_t position) const // bitwise const声明,
5. { return pText[position]; } // 但其实不适当.跟之前相比少了一个const!
6. private:
7. char* pText;
8. };
operator[]实现代码并不更改私有变量pText,于是编译器为operator[]产出目标码,并认定它是bitwiseconst。
1. const CTextBloc