基本概念

引用的本质就是指针,下面两行代码的底层逻辑是一致的

int *p   = &a
int &ref = a

如果添加 const 限制词,表示不能通过 *pref 间接修改 a 的值

const int *p   = &a
const int &ref = a
// 等价于
int const *p   = &a
int const &ref = a

一般常用于参数声明,如

void foo(const int *p)
void foo(const int &ref)

如人们所知,引用只能指向变量。但添加 const 关键字的引用,可以指向临时值

int &ref       = a   // ok
int const &ref = a   // ok
int &ref       = 10  // error
int const &ref = 10  // ok

但是需要注意,非 const 引用不能指向 const 变量

const int a = 10
int &ref       = a  // error
int const &ref = a  // ok

若 const 出现在 * 号后面,就代表指针变量 p 本身不可被修改

int* const p = &a
*p = 20  // ok
 p = &b  // error

因此发现,const 关键字将修饰它右边的第一个元素。

进阶写法

指向指针变量

int *p   = &a
int **pp = &p
const int *p   = &a
const int **pp = &p

最后一片代码中的 pp 类型为 const int**,表示 **pp 不可修改。pp*pp 可以修改,其中 *pp 指向指针变量 p

引用指针变量

int* const &ref = p
// 等价于
int* const *pointer = &p

表示 pointer 引用了一个 int* 类型的变量。

  • 由于 const 的修饰,无法通过 *pointer 改变指针 p 的指向;
  • 但可以通过 **pointer 改变 *p 的值;
  • 对应到引用,则是 ref 不可修改,*ref 可以修改。

引用指针常量

const int* &ref = p
// 等价于
const int* *pointer = &p

由于 const 修饰它右边的第一个元素,因此 pointer 的类型为 const int**

  • 其中 **pointer 不可修改,*pointer 可以修改;
  • 对应到引用,则是 *ref 不可修改,ref 可以修改。

常引用指针常量

// 以下两种声明都支持
int* p = &a
const int* p = &a
const int* const &ref = p
// 等价于
const int* const *pointer = &p

从后往前看,指针 *pointer 指向了一个 const int* 类型的变量。

  • 由于 *pointer 被 const 修饰,因此无法通过 *pointer 间接修改 p 的指向,故 ref 无法修改;
  • 由于 int* 类型被 const 修饰,因此无法通过 **pointer 间接修改 *p 的值,故 *ref 无法修改;
  • 因为最后一个 const 的出现,使得原本的 const int** 变为了 const int* 类型,又因为 const 具有向上兼容性,故同时支持 int*const int* 两种类型。