条款03:尽可能使用const(Use const whenever possible)
1.const == 奇妙的事
const的一件奇妙的事是,他允许你定义一个约束,(告诉编译器,这是一个“不该被改动的对象”),并且你这样做了之后编译器会协助你执行这条约束,使编译器成为你的助手。
这确实是一件奇妙的事,程序员其实就是在用特定的语言进行说话,而编译器就是你的翻译者,程序员和你的“翻译者”的密切配合才能出好的程序。
2.const语法变化多端(变量上的)
(1)语法
相信用过的人都见过和尝试过这些看着让人头疼的语法了吧。指针和引用都有不同的const语法
1 const int *p; // 2 int const *p; //前面两种形式不一样,但是是同一种。都是指针所指向的变量是修饰为常量 3 int *const p; //const修饰的是指针变量本身,指针变量本身是常量 4 const int *const p; //合以上两者
这里不得不提一下来自《C++ Templates》作者序的一个说法:
我们都知道int const *p与const int *p 是等同的
但是这里我们更趋向于int const *p
这里提出两点原因:
a.指针对问题“什么是恒定不变的?” int const *p提供很容易理解的答案,“恒定不变的部分”是const限定符前面的int
int const *p //恒定不变的是int (指针所指向整数的部分,整数类型是int) int* const p //恒定不变的是int*(指针变量本身,指针变量的类型是int*)
提供另外一种理解const指针的方法
b.设计到使用模板时一个常用的语法替换原则
typedef char* CHARS; typedef CHARS const CPTR; //指向char类型的常量指针(指针本身是不变) //当我们用CHARS所代表的含义对它进行替换之后 typedef char* const CPTR//任然是char类型的常量指针 //但是当我们把const位置放在前面时,就不在实用了 typedef const CHARS CPTR;//指向char类型的常量指针 //替换之后 typedef const char* CPTR;// 指向常量的char类型的指针
(2)STL迭代器的const
迭代器是以指针为根据塑造出来的,所以迭代器的作用就像T* 指针。
所以声明迭代器为const就像声明指针为const一样(即声明一个T* const指针),迭代器不能指向不同的对象,所指向的对象的值可以改变
std::vector<int> vec; ... const std::vector<int>::iterator iter = vec.begin(); //iter的作用像个T* const *iter = 10; //改变iter所指向的物 ++iter; //错误!!!iter本身是const的 std::vector<int>::const_iterator cIter = vec.begin(); //cIter的作用想个 const T* *cIter = 10; //错误!!!cIter所指向的为const ++cIter; //没问题。
迭代器的使用:const iterator iter; const_iterator iter
(3)const用于函数的返回值和参数值
利用const本身的属性来解决一些不变问题。
3.const成员函数
(1)目的,是为了确认该成员函数可作用于const对象身上。
重要:a.const使你的class接口比较容易被理解,这样可以很清楚的知道哪个函数可以改动对象内容哪个不可以;这很重要
b.它们使“操作const对象”成为可能。(很多时候以pass by reference-to-const方式传递对象),这样可以使const对象呗调用