当const遇见指针(常量指针与指针常量)
国内的很多教材、教程里常常提到常量指针和指针常量,很多公司面试的时候也会问到区别。乍一看好像很绕,其实也不难,下面的例子将具体的讲解一下。
char greeting[] = "Hello";
char* p = greeting; // non-const pointer, non-const data
const char* p = greeting; // non-const pointer, const data
char* const p = greeting; // const pointer, non-const data
const char* const p = greeting; // const pointer, const data
凡是被const修饰的量,它的值都不允许被修改。在上面的例子中,const的位置决定了这个指针本身是一个常量,还是指针所指向的值是一个常量。如果你不能很好地区分,那么这里有一个很好记的法则,
- 如果关键字const出现在星号左边,表示被指物是常量;如果出现在星号右边,表示指针自身是常量;如果出现在星号两边,表示被指物和指针两者都是常量。
对于上述的第一种情况,即如果被指物是常量的话,有些程序员会将关键字const写在类型之前,有些人会把它写在类型之后、星号之前。两种写法的意义相同,所以下列两个函数接受的参数类型是一样的:
void f1(const Widget* pw);
void f2(Widget const * pw);
目前这两种形式都有人在使用,所以大家应该试着去习惯它们。
当const遇见STL迭代器
STL迭代器是以指针作为模板塑造出来的,所以迭代器的作用就像是一个T* 指针。声明迭代器为const就像声明指针为const一样(即声明一个T* const指针),表示这个迭代器不能指向不同的东西,但是它所指向的东西是可以改动的。如果你希望迭代器所指向的东西不可以被改动(也就是const T* 指针),你需要的是const_iterator。下面有一个针对此问题的示例:
std::vector<int> vec;
const std::vector<int>::iterator iter = vec.begin(); // iter不允许被修改
*iter = 10; // 正确,指向的值可以改变
++iter; // 错误!
const std::vector<int>::const_iterator cIter = vec.begin(); // iter指向的值不允许修改
*cIter = 10; // 错误!
++cIter; // 正确!
当const遇见函数声明
这也是const最大的威力。在一个函数的声明式中ÿ