指向const对象的指针

如果指针指向const对象,C++语言强制要求指向const对象的指针也必须具有const特性。

const int a = 10;
const int *pa = &a;

const限定了pa指针所指向的对象本身,而并非pa本身,即允许给pa重新赋值,但不允许通过pa改变a的值。即:

const int a = 10;
const int b = 20;
const int *pa = &a;
*pa = 20;    //错误,不允许通过pa改变a的值
pa = &b;    //正确,允许给pa重新赋值

注意:

  • 不能把一个 const 对象的地址赋给一个非 const 对象的指针
  • 不能使用 void* 保存 const对象 的地址,得使用 const void*
  • 允许把 非const对象 的地址赋给 const修饰的指针,但是一旦把 非const对象 的地址赋值给 const修饰的指针,就不能通过 const指针 修改所指向的变量,但变量本身是可以修改的。即:
int a = 10;
const int *pa = &a;    
*pa = 20;   //错误,不能通过 const指针 修改所指向的变量
 a = 20;     //正确,变量本身可以修改
cout << *pa << endl;   //最后输出结果为20

const指针

上面我们说过,对于指向const对象的指针,虽然不能通过指针修改指向的变量,但是指针本身是可以再赋值的。

除了上面的指针外,C++还提供了一种const指针 – 指针本身的值不能改变。

int a = 10;
int *const pa = &a;

对于这种形式的指针,指针pa值便不可修改,但是pa指向的值可以修改,即:

int a = 10;

int b = 30;

int *const pa = &a;

*pa = 20;   //这样是正确的,pa指向的值可以修改

pa = &b;     //这样写是错误的,指针pa值不可修改

注意:

  • 对于第一种指向const对象的指针,因为指针本身并不是const,所以在定义时不需要初始化。
  • 对于第二种const指针,因为指针本身是const修饰的,与任何const变量一样,const指针也必须在定义的时候初始化。

指针和typedef

在typedef中使用指针往往会带来意外的结果,看下面的例题:

typedef string *pstr;
const pstr cstr;

请问cstr是什么类型?

可能乍一看,const pstr cstr <=> const string *cstr,但这是错误的。因为我们都知道如果指针本身并不是const,只是指向const对象,那么在定义时不需要初始化;如果指针本身const 指针,那么必须在定义的时候初始化,就如同下面一样:

const int *pint;    //可以不用初始化

int *const ppint;   //不可以不初始化,这样写是错误的

我们把

typedef string *pstr;
 const pstr cstr;

写到编译器里,编译器会提示错误,说明 const pstr cstr 不初始化是错误的,所以 const pstr cstr!= const string *cstr

错误的原因在于将 typedef 当做文本扩展了。声明 const pstr 时,const修饰的是pstr,pstr是一个指针。因此,该声明语句应该是把cstr定义为指向string类型的const指针,所以:

const pstr cstr <=> string *const cstr