指针、引用和常量的关系

前言

指针、引用和常量的关系因为不同位置、能够相互嵌套(套娃)而异常复杂。文章简要介绍它们的区别,并总结区分技巧。


指针和引用

指针是对象,引用不是对象

对象的概念宽泛,不易理解。在此可以理解为变量,一个变量是一个对象

  • 指针不必须初始化
  • 引用只是 为一个已经存在的对象所起的另一个名字(别名)
  • 引用必须初始化(初始化时的右值是一个已经存在的对象

示例:

cpp 复制代码
int *p;	

int val;	//一个已经存在的"对象"
int &ref = val;

int &ref1;	//×

指向引用的指针

不存在该定义。因为引用不是对象 ,所以不能定义指向引用的指针。 示例:

cpp 复制代码
int val;
int &ref=val;
int &*p=ref;	//×

指向指针的引用

因为指针是对象 ,所以能定义指向指针的引用。 示例:

cpp 复制代码
int *p;
int *&ref = p;

分析技巧

从左往右阅读变量定义:

  • 离变量名最近的符号,对变量的类型有最直接的影响。表述为:"...类型"
  • 其余符号确定变量名作用的 类型。表述为:"指向 ...类型的"

在示例中,离变量名ref最近的符号是&,表述为"引用类型 "。其余符号是int *,表述为"指向 整型指针类型的"。

从右往左理解变量定义:

  • 离变量名最近的符号,对变量的类型有最直接的影响。表述为:"...类型"
  • 其余符号确定变量名作用的 类型。表述为:"作用于...类型"

在示例中,离变量名ref最近的符号是&,表述为"变量ref 引用类型"。其余符号是int *,表述为"变量ref作用于整型指针类型"。

综上,"int *&ref = p;"是"指向 整型指针类型的 引用类型 "(阅读定义),本质上是"指针的别名",右值是指针(理解定义)。


变量和常量

一个变量的 不能被改变,该变量常量。

变量的概念宽泛,不易理解。在此可以理解为变量 常量,具有不能被改变的特性

示例:

cpp 复制代码
const int val = 0;	//使用"const"限定符修饰"变量"

指针类型的常量

因为指针是对象 ,所以能定义指针类型的常量。 示例:

cpp 复制代码
int val = 0;
int *const p = &val;

分析技巧

从左往右阅读变量定义:

  • 离变量名最近的符号,对变量的类型有最直接的影响。表述为:"...类型"
  • 其余符号确定变量名作用的 类型。表述为:"指向 ...类型的"

在示例中,离变量名p"最近的符号是"const",表述为"常量类型 "。其余符号是"int *",表述为"指向 整型指针类型的"。

从右往左理解变量定义:

  • 离变量名最近的符号,对变量的类型有最直接的影响。表述为:"...类型"
  • 其余符号确定变量名作用的 类型。表述为:"作用于...类型"

在示例中,离变量名"p最近的符号是const,表述为"变量p 常量类型"(虽然将常量表述为一种数据类型不太准确)。其余符号是"int *",表述为"变量p作用于整型指针类型"。

综上,"int *const p = &val;"是"指向 整型指针 常量类型",即"指针类型的常量"(阅读定义)。

  • 不能修改其所指对象的地址 (因为自身的常量特性)
  • 是否能修改所指对象的 取决于所指对象的类型。若指针所指对象是非常量,则可修改;反之不可(因为所指对象的常量特性)

(理解定义)


引用类型的常量

不存在该定义。因为引用不是对象 ,所以不能定义引用类型的常量。 示例:

cpp 复制代码
int val = 0;
int &const ref = val;	//×

指向常量的指针

示例:

cpp 复制代码
const int val = 0;
const int *p = &val;

分析技巧

从左往右阅读变量定义:

  • 离变量名最近的符号,对变量的类型有最直接的影响。表述为:"...类型"
  • 其余符号确定变量名作用的 类型。表述为:"指向 ...类型的"

在示例中,离变量名p最近的符号是*,表述为"指针类型 "。其余符号是const int,表述为"指向 常量整型(整型常量)类型的"。

从右往左理解变量定义:

  • 离变量名最近的符号,对变量的类型有最直接的影响。表述为:"...类型"
  • 其余符号确定变量名作用的 类型。表述为:"作用于...类型"

在示例中,离变量名p最近的符号是*,表述为"变量p 指针类型"。其余符号是const int,表述为"变量p作用于常量整型(整型常量)"。

综上,"const int *p = &val;"是"指向 整型常量 指针类型",即"指向常量的指针"(阅读定义)。

  • 普通指针不可指向常量
  • 指向常量的指针可指向常量
  • 指向常量的指针可指向非常量
  • 不能修改所指对象的值(因为所指对象的常量特性)

(理解定义)


指向常量的引用

示例:

cpp 复制代码
const int val = 0;
const int &ref = val;

分析技巧

从左往右阅读变量定义:

  • 离变量名最近的符号,对变量的类型有最直接的影响。表述为:"...类型"
  • 其余符号确定变量名作用的 类型。表述为:"指向 ...类型的"

在示例中,离变量名ref最近的符号是&,表述为"引用类型 "。其余符号是const int,表述为"指向 常量整型(整型常量)类型的"。

从右往左理解变量定义:

  • 离变量名最近的符号,对变量的类型有最直接的影响。表述为:"...类型"
  • 其余符号确定变量名作用的 类型。表述为:"作用于...类型"

在示例中,离变量名p最近的符号是&,表述为"变量ref 引用类型"。其余符号是const int,表述为"变量ref作用于常量整型(整型常量)"。

综上,"const int &ref = val;"是"指向 整型常量 引用类型",即"指向常量的引用"(阅读定义)。

  • 普通引用不可指向常量
  • 指向常量的引用可指向常量
  • 指向常量的指针可指向非常量
  • 不能修改所指对象的值(因为所指对象的常量特性)

(理解定义)


技巧

从左往右阅读变量定义

  • 离变量名最近的符号,对变量的类型有最直接的影响。表述为:"...类型"
  • 其余符号确定变量名作用的 类型。表述为:"指向 ...类型的"

从右往左理解变量定义

  • 离变量名最近的符号,对变量的类型有最直接的影响。表述为:"...类型"
  • 其余符号确定变量名作用的 类型。表述为:"作用于...类型"

顶、底层常量

  • 针对指针类型的判别,因为指针本身是一个对象,其可以指向另一个对象(概念实际上可以扩展到引用等复合类型)
  • 离变量名最近的const符号,是顶层
  • 离变量名最远的const符号,是底层
  • 顶层常量,表示对象本身是常量
  • 底层常量,表示对象所指的对象是常量

示例:

cpp 复制代码
int val = 0;
int *const p1;	//顶层常量,不能改变p1的值
const int *p2;	//底层常量,不能通过p2改变所指对象val的值
  • 执行对象的拷贝(赋值)操作时,拷入和拷出的对象必须具有相同的底层常量资格;或者两个对象的数据类型能够相互转换,一般非常量能够转换成常量(除基本类型外

示例:

cpp 复制代码
int val = 0;
int *p1 = &val;
const int *p2 = &val;
const int *p3 = &val;

p1 = p2;	//× 不具有相同的底层常量资格,常量不能够转换成非常量
p2 = p3;	//√	具有相同的底层常量资格
p2 = &val;	//√	非常量能够转换成常量

const int val2 = 0;
val = val2;	//√	基本类型的常量能够转换成非常量

总结

  • 指针、引用和常量的关系因为不同位置、能够相互嵌套(套娃)而异常复杂
  • 建议分别或集中对比,简要 了解其概念、理解几个简单示例。在理解的基础上总结区分技巧即可
  • 实际编程中几乎遇不到、用不到它们的复杂组合,可无需咬文嚼字、刨根问底

作者的话

  • 作者反复阅读书籍中对指针、引用和常量的描述,边理解边总结
  • 实际上这篇文章内容质量并不好,因为作者在分析时还是很容易懵逼。至少尽力地将自己的理解更好地表述出来
  • 文章内容基于读者对指针、引用和常量概念有一定的理解
  • 一些详细概念请参阅其他资料
  • 文章在描述时有疑惑的地方,请留言,定会一一耐心讨论、解答
  • 文章在认识上有错误的地方, 敬请批评指正
  • 望读者们都能有所收获

参考资料

《C++ Primer》中文版(第5版)作者:Stanley B. Lippman,Barbara E. Moo,JoséeLaJoie

相关推荐
烟花巷子1 小时前
C++中的解释器模式
开发语言·c++·算法
暮冬-  Gentle°2 小时前
C++中的策略模式高级应用
开发语言·c++·算法
txinyu的博客2 小时前
解析muduo源码之 HttpRequest.h
c++
2401_879693872 小时前
C++中的代理模式高级应用
开发语言·c++·算法
王璐WL2 小时前
【c++】隐藏的this指针
c++
2501_924952692 小时前
C++中的枚举类高级用法
开发语言·c++·算法
2401_873204652 小时前
代码覆盖率工具实战
开发语言·c++·算法
少司府2 小时前
C++基础入门:第一个C++程序
java·c语言·开发语言·c++·ide
不染尘.2 小时前
欧拉路径算法
开发语言·数据结构·c++·算法·图论