理清常量指针和指针常量

鉴于这玩意儿的叫法一团乱麻,甚至存在完全相反的叫法,实在是令人头大,故此本人选择如下叫法1

  • 指向常量的指针变量:const int* p
  • 指向变量的指针常量:int* const p
  • 指向常量的指针常量:const int* const p
    此外,const int *p 与 int const *p 是等价的。

判断方法

本人采用的方法是看 const 和 * 的相对位置。

如果 const 在 * 和 p 之间,说明 const 修饰的是 p,即指针为常量;

反之,则说明 const 修饰的是 *p,即所指的值是常量。

关于引用

按理说,引用也应该有如下两种形式:

  • const int& p
  • int& const p

然而,现实情况是第二种不存在,因为引用只能在初始化时绑定一个对象(左值),之后不能再重新绑定其它对象,对引用的操作实际上都是对引用绑定的对象进行操作,即绑定关系已不可更改,用const修饰引用本身无意义。

符合类型

指向指针的指针

1
2
3
int ival = 1024;
int *pi = &ival; // pi指向一个int型的数
int **ppi = π // ppi 指向一个int型的指针

此处pi是指向int型数的指针,而ppi是指向int型指针的指针。

1
2
3
4
5
cout << "The value of ival\n"
<< "direct value: " << ival << "\n"
<< "indirect value: " << *pi << "\n"
<< "doubly indirect value: " << **ppi
<< endl ;

该程序使用三种不同的方式输出了变量ival的值:

  • 第一种直接输出;
  • 第二种通过int型指针pi输出;
  • 第三种两次解引用ppi,取得ival的值。

指向指针的引用

引用本身不是一个对象,因此不能定义指向引用的指针。但指针是对象,所以存在对指针的引用:

1
2
3
4
5
int i = 42;
int *p; p是一个int型指针
int *&r = p; r是一个对指针p的引用
r=&i; r引用了一个指针,因此给r赋值&i就是令p指向i
*r=0; 解引用r得到i,也就是p指向的对象,将i的值改为0

面对一条比较复杂的指针或引用的声明语句时,从右向左阅读有助于弄清楚它的真实含义。