引言
阅读完《C++ Primer》2.4小节,对const
限定符下的引用和指针的理解有点迷茫,因此本文总结了const
限定符下的指针和引用的使用方式。
const
修饰符用来定义常量,可以有两种作用方式。当其修饰对象时,例如const int
, int* const
,该对象必须显式初始化,此时称其为顶层const
;当其修饰类型说明符时,例如const int&
, const int*
,该对象无须显式初始化,此时称其为底层const
。
引用
引用是已存在的对象的一个别名,这里的对象是指某块内存空间。
普通引用
int&
- 普通引用必须显式初始化;
- 不能用字面值和常量初始化;
- 普通引用类型必须与其所引用对象的类型一致;
- 普通引用不可以使用常量引用初始化;
- 普通引用可以赋值,赋值会改变其绑定对象的值。
常量引用
const int&
- 常量引用必须显式初始化;
- 可以用字面值、非常量来初始化常量引用;
- 常量引用类型与其所引用对象的类型可以不一致,在常量引用绑定非常量中详细讲述;
- 常量引用可以使用普通引用进行初始化;
- 常量引用不可以赋值。
常量引用绑定非常量
- 用非常量初始化常量引用,且类型一致时,非常量修改时,常量引用一起改变;
int i = 10;
const int& cri = i;
cout << cri << endl;
i = 20;
cout << cri << endl;
输出为
10
20
- 用非常量初始化常量引用,且类型不一致时,非常量修改时,常量引用不变。
int i = 10;
const int& cri = i;
cout << cri << endl;
i = 20;
cout << cri << endl;
输出为
10
10
指针
指针是指向已存在对象的一个对象。
普通指针
int*
- 不必显式初始化;
- 不可以指向字面值和常量对象;
- 普通指针类型必须和其指向的对象类型一致;
- 普通指针不能用指向常量的指针赋值,可以用常量指针赋值;
- 普通指针可以赋值,会让指针指向另外一个对象;
- 普通指针解引用后也可以赋值,会改变其指向对象的值。
指向常量的指针
const int*
- 不必显式初始化;
- 可以指向常量或者非常量,不能指向字面值;
- 指向常量的指针类型必须与所指对象类型一致;
- 指向常量的指针可以用普通指针赋值,也可以用指针常量赋值;
- 指向常量的指针可以赋值,让指针指向其他对象;
- 指向常量的指针解引用后无法赋值,无法修改指向对象的值。
指针常量
int* const
- 必须显式初始化;
- 不能用字面值和常量初始化;
- 指针常量的类型必须与所指对象类型一致;
- 指针常量可以用普通指针赋值,不能用指向常量的指针赋值;
- 指针常量不可以赋值,一旦初始化,就不能指向其他对象;
- 指针常量解引用后可以赋值,可以修改指向对象的值。
顶层const
和底层const
通过以上总结,不难发现,只有内置类型和指针复合类型具有顶层const
,顶层const
具有以下共同特点。
- 必须显式初始化;
- 不能用底层const或者无const初始化;
只有指针和引用复合类型都具有底层const
,底层const
具有以下特点。
- 无须显式初始化,特别的,引用需要显式初始化;
- 可以用常量或者非常量初始化,特别的,引用还可以用字面值初始化;
- 不能用顶层
const
或者无const
赋值;
总结
总结来说,顶层const
和底层const
的概念并不能很好地帮助我们理解好const
限定符下面的指针和引用,所以不必细抠这两个概念,而应该将精力放在每个const
修饰下的具体类型上,结合const
,引用及指针的基本概念来理解。