条款03:尽可能使用const
面对指针的时候,既可以指出指针自身,也指针所指向的事物,或者两者都是 const。
char str[] = "hello"; char* p = str; //指针不是const,字符串也不是const const char* p = str; //指针不是const,字符串是const char* const p = str; //指针是const,字符串不是const const char* const p = str; //指针是const,字符串也是const
为了方便记忆。如果关键字const出现在星号左边,表示被指物是const。如果const出现在星号右边,表示指针自身是const。如果出现在星号两边,则两者都是const。
声明迭代器const就像声明指针为const一样,表示这个迭代器不得指向不同的东西,但是他所指向的东西是可以改动的。如果你希望迭代器所指向的东西不可以被改动,你需要的是const_iterator.
vector<int>vec; const vector<int>::iterator iter = vec.begin(); //这里迭代器类似于 T* const 指针的指向不能改变 *iter = 10; //没问题,改变iter所指物 ++iter; //error 不可以改变指向 vector<int>::const_iterator cIter = vec.begin() //类似于T* const 所指的对象不可改变
另函数返回一个常量值,往往可以降低因为客户错误而造成意外,而又不至于放弃安全性和高效性。
考虑下面一种情况
class myInt{ public: int num; myInt(int a){num = a;} }; const myInt operator*(const myInt& li,const myInt& ri){ const myInt aa(li.num*ri.num); return aa; }
至于为什么要把返回值设为const。原因是如果不这样,客户就会写出如下代码:
myInt a,b,c; (a*b) = c;
如果操作符*的返回值是const的,这样的代码就是直截了当的不合法的。将operator* 返回值设为const就是为了避免那个没有意义的赋值动作。
const 成员函数
将const实施与成员函数的目的,是为了确认该函数可作用于const对象。当两个成员函数只是const属性不同的时候,他们是可以重载的。
class myInt{ public: int num; myInt(int a){ num = a; } int& getValue(){ int res = num*num; return res; } const int& getValue() const{ const int res = num; return res; } };
我们可以这样使用上述函数
myInt mi(10); cout<<mi.getValue()<<endl; //使用non-const函数,输出100 const myInt ma(20); cout<<ma.getValue()<<endl; //使用const函数,输出20
要注意这里的返回值是一个指向int的引用。这是因为,如果返回的是一个int的话,下面的语句将无法通过编译
mi.getValue()+=1;
那是因为,如果返回的是内置类型,那么改动函数返回值从来都不合法,即便这样是合法的,你改变的也是mi.value的一个副本,而不是这个变量本身。