复合类型——指针和引用

概述

复合类型,顾名思义就是指基于其他类型定义的类型,主要有***指针***与***引用***。本文将先分别介绍这两种类型,接着将介绍二者之间的异同之处。
一般来讲,一条声明通用的格式为:基本数据类型 声明符。在简单声明语句中,声明符就是变量名,换句话说,此时的变量类型就是声明符前面的基本数据类型。而复合类型就是一种基于基本数据类型的更为复杂的数据类型。

指针

指针定义

*指针是一中“指向”另外一种类型的复合类型。简而言之,指针是一种实现对对象间接访问的类型。指针本身也是对象,该对象存放了指针所指对象的地址,以此来实现对对象的间接访问。
定义指针类型的方法就是将声明符写成*p格式,其中p是变量名,在一条声明语句中可以声明多个指针类型的变量,每个变量名前必须有
。具体格式如下:

int *p, *q; //声明了两个指针类型的变量p和q,p,q都指向int类型的对象
double *p, i; //声明了一个指令类型的变量p,该变量p指向一个double类型的对象和一个double类型变量i

获取对象地址

既然指针对象存储的是指针所指对象的地址,那么如何获取对象的地址呢?通常在变量名前加**&**符号来获取对象的地址。

int i = 41; //定义并初始化一个int类型的变量i
int *p = &i; //定义一个指向int类型对象的指针p,p存放的是i的地址,也就是说p是指向i的指针。

注意:这里的符号&取地址符**,和之后将要在引用章节中提到的**&有着不同含义在那里是引用声明符**。

一般来说,指针的类型必须和它所指向的对象严格匹配。因为在一条声明语句中指针的类型实际上是用来指定它所指向对象的类型,所以二者必须严格一致。

double d; //声明一个double 类型的对象d
int *p = &d; //错误:不可以用int类型的指针指向一个double类型的对象
double *q = &d; //正确:可以用double类型的指针指向一个double类型的对象

###指针的值
通常,指针的值无外乎以下4中:

  • 指向一个对象
  • 指向相邻对象所占空间的下一个位置
  • 空指针,如int *p = nullptr;
  • 无效指针,除以上各种情况
赋值与访问

赋值和访问可以分为对指针本身的赋值和访问以及对指针所指对象的赋值和访问。

char *p1 = "abc", *p2= p1;//指针p1和p2都指向字符串"abc"的首地址
int a = 2, b = 3;
int *p3 = &a;//对指针本身的赋值,将int类型变量a的地址赋值给p3
p2 = p1 + 1;//对指针本身的运输和赋值,此时p2将指向字符串"abc"的'b'的地址
cout << *p3 << endl;//访问p3所指向的对象

引用

**引用是为对象取的一个别名,引用类型引用另外一种类型通过将声明符写成&f形式来定义引用类型。

int ival = 2;
int &reval = ival;//引用必须初始化

学习引用必须时刻注意它的定义:引用是为对象起的另外一个***别名***,简而言之,提到引用第一反应就是***别名***。这样,很多问题就迎刃而解,比如:引用必须初始化,引用是别名,不初始化怎么知道它是哪个对象的别名,再比如,引用一经初始化就不能再指向其他对象了,否则,作为别名却指向多个对象,这样就相当于一个一个引用是多个对象的别名。
既然引用就是其所引用对象的别名,所以,对引用的操作就是对所引用对象的操作。

const限定符与指针和引用

首先简单的介绍一下***const***这个声明限定符,被const修饰的变量和普通变量大体没有出别,本const修饰对象主要限制在于对该变量的操作指限于不改变其内容的操作。还有一个必须了解的是,const只影响被它修饰的对象,时刻记住这一点是十分有必须要的。

指向常量对象的指针

指向常量的对象的指针,顾名思义,就是指针所指向的对象是常量,但是也不完全对,因为这样乍看好像并没有什么问题,但是如果细想,被指对象是常量,当然是不想被修改,现在有指针指向它,是不是可以通过指针修改它呢?举例说明:

const double pi = 3.14;
double r = 1;
double *p = & pi; /*错误:变量pi是一个double类型常量,如果本语句正确,那么程序员将可以通过指针p来改变pi的值了*/
const double *p1 = &pi; /*正确:指向常量对象的指针,无论通过指针p1还是变量pi本身都不能改变pi的值*/
const double *p2 = &r;//正确:将一个指向常量的指针指向一个普通变量

从上面的代码中,我们可以看出,可以将一个指向常量的指针指向一个常量或者普通变量,二者的主要出别在意前者不论通过指针还是变量本身都不能改变变量的值,而后者则不同——不可以通过指针来改变变量的值,但是可以通过变量本身来改变。总之,出别这一点的关键在要始终记住,const影响的只是它所修饰的那个变量,和其他的没有关系。

常量指针

现在,我们应该会想到,指针需要从两个方向来思考——指针本身和指针所指向的对象。指针本身也是对象当然也可以被const修饰。这就是这一小结中的***常量指针***。正如该名称所示,常量修饰的是***指针***,就是说常量指针一经初始化后就不能再指向其他对象。那么问题又来了,是否可以通过常量指针修改其指向对象的值呢?答案是肯定的,正如上文所讲,const 只影响被其修饰的对象,和其他对象无关。

double pi = 3.14;
double *const p = &pi; //常量指针

从上面的实例代码中我们可以知道,常量指针所指对象也不必是常量。

常量引用

和指针类似,引用也可以指向一个常量对象,也可以通过const限制引用不可修改所指对象。与指针不同之处在于两者都是常量引用,即对const的引用。这里,我们要记住,引用不是对象,只是被引用对象的别名而已。引用一经绑定便不可以改变其绑定的对象,那么就不存在类似与常量指针的概念了,换而言之,在引用关系这个层面上是不受const的影响的。const所能够影响的只有对对象的操作上,因此,在讲const和引用时,我们只需关注引用和被引用对象操作上,不必关心引用关系。可能有读者就会有疑问了,如果一个对象可以通其本身来改变,但是不能通过引用来改变该如何操作?

int a = 12;
const b = 13;
const int &c = b;//将常量引用绑定到一个常量上
const int &d = a; //将一个常量绑定到一个普通对象上

此次,容易使人迷惑的是,一个对const 的引用却可以绑定到一个普通变量上。其实,也不难理解,因为我们有上面的需求——可以通过变量本身改变变量额度值,但是不可以通过引用来改变。要更好的理解这个问题,我们需要知道它是如何实现的,const int &d = a其实等价于:

const int temp = a;
const int &d = temp;

简单来讲,就是变压器对代码做了转换,d实际上绑定到了一个***临时变量*** temp上。

总结

  1. 区别指针和指针所指向的对象
  2. 指针是对象,其中存放的是其所指对象的地址
  3. 指针所指对象是,指针对象所存地址对应空间存放的内容
  4. const限定符只影响它所修饰的变量。
  5. 引用是变量的一个别名,记住这一点将解决大部分关于引用的疑惑
  6. 变量和它的引用之间是绑定关系,而非赋值关系,即,对引用值的修改将改变变量的值
  7. 定义引用时必须对其进行初始化,且初始化必须是一个变量,否则,将不知道引用到底是谁的别名
  8. 初始化一旦完成,变不可更改,也就是说该引用不可再绑定到其他变量上了,否则,一个别名将是若干个变量的别名,这样将导致不知道别名到底绑定了哪变量了。
  9. 因为引用只是一个别名而已,所以引用不是对象,没有实际的地址,进而得出,不能定义指向引用的指针

关注作者公众号

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值