常量引用,指向常量的指针和常量指针的区别

引言

阅读完《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,引用及指针的基本概念来理解。

猜你喜欢

转载自blog.csdn.net/Abecedarian_CLF/article/details/104844294