Effective C++读书笔记(2)(一)

2014-11-24 12:20:02 · 作者: · 浏览: 2

条款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 vec;
2. ...
3. const std::vector::iterator iter = vec.begin( ); //T* const
4. *iter = 10; //没问题,改变iter所指物
5. ++iter; //错误!iter是const
6. std::vector::const_iterator cIter = vec.begin( );// const T*
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