3.C++中的复合类型-引用和指针

一个声明语句由一个基本数据类型和紧随其后的一个声明符列表组成。
最简单的如 int i;int 就是基本数据类型,声明符其实就是变量名i。而以下提到的引用和指针具有更复杂的声明符,它基于基本数据类型得到更复杂的类型,并把它指定给变量。

1. 引用

引用(reference)类似电脑中软件的快捷方式,它为对象取了一个别名。通过将声明符写成&d的形式来定义引用类型。

int val=1;
int &rval = val;//rval指向val(是val的另一个名字)
int &val2;//错误,引用必须初始化
  1. 引用必须初始化:C++中的引用在定义时必须初始化,因为它们只能代表一个已经存在的对象。一般在初始化变量时,初始化值会被拷贝到新建的对象中;但是在定义引用时,程序会把引用和它的初始值绑定在一起,而不是将初始值拷贝给引用。一旦初始化完成,引用将和它的初始值一直绑定在一起。因为无法令引用重新绑定到另一个对象,所以引用必须初始化
  2. 引用并非对象:正如之前所说,引用就是一个别名,它只是为一个已存在的对象所起的并一个名字,定义一个引用之后,对其的所有操作都是在与之绑定的对象上进行的,其地址也是其绑定对象的地址。
  3. 不存在引用的引用:引用本身不是一个对象,因此不能定义引用的引用。
    你可能对以下代码感到迷惑:
//声明了两个整数变量并分别初始化为1和2
int val1 = 1;
int val2 = 2;
//声明了两个整数引用,并分别将其绑定到 val1 和 val2。
int &rval1 = val1;
int &rval2 = val2;
//声明了另一个整数引用,并将其绑定到 val1 迷惑点1
int &rval3 =rval1;
//将 rval3 引用的对象(即 rval1 引用的对象 val1)的值修改为 val2 的值。
//这并不会改变 rval3 引用的对象,它仍然引用 val1。迷惑点2
rval3 = val2;

int &rval3 =rval1; 其本质仍是将rval3绑定到val1上,不是引用的引用。
rval3 = val2;并不会改变rval3 引用的对象,只是将rval3 引用的对象(val1)的值改为 val2 的值.

  1. 除了两种特殊情况(指向常量的引用和派生类引用可以赋值给基类引用),其他所有引用的类型都要和与之绑定的对象严格匹配。并且,引用只能绑定在对象上,而不能与字面量或某个表达式的计算结果绑定在一起。
int & refval4 = 10;//报错 引用类型的初始值必须是一个对象
double dval = 3.14;
int &refval5=dval;//报错,此处引用类型的初始值必须是int型对象

2. 指针

指针也就是内存地址,指针变量是用来存放内存地址的变量,在同一CPU构架下,不同类型的指针变量所占用的存储单元长度是相同的;而存放数据的变量因数据的类型不同,所占用的存储空间长度也不同。有了指针以后,不仅可以对数据本身,也可以对存储数据的变量地址进行操作。 在这里插入图片描述

与引用的差异

  1. 指针本身是一个对象,拥有属于自己的内存地址,允许对指针赋值和拷贝,而且在指针的生命周期内它可以先后指向几个不同的对象。
  2. 指针无需在定义时赋值,与其他内置类型一样,在块作用域内定义的指针如果未初始化,也将拥有一个不确定的值。

和引用的相似
除了两种特殊情况(指向常量的指针和派生类指针可以赋值给基类指针),其他所有指针的类型都要和与之绑定的对象严格匹配

指针的定义:将声明符写成*d的形式。

    int p1,*p2;//p1是int型对象,p2是一个指向int型对象的指针

获取对象的地址:指针存放某个对象的地址,要想获取该地址,需要使用取地址符&

    int i = 42;
    int *p1 = &i; //p1存放i的地址,或者说p1是指向变量i的指针

指针值
1.指向一个对象;
2.指向紧邻对象所占空间的下一个位置;
3.空指针,意味者指针没有指向任何对象;
4.无效指针,也就是上述情况之外的其它值。
试图拷贝或者以其他方式访问无效指针的值都将引发错误,但编译器并不负责检查此类错误。

利用指针访问对象
如果指针指向了一个对象,则允许使用解引用符*来访问该对象。

    int i = 42;
    int *p1 = &i; //p1存放i的地址,或者说p1是指向变量i的指针
    cout<<*p1;

对指针解引用会得出其所指的对象,因此如果给解引用的结果赋值,实际上也就是给指针所指变量赋值。

*p1 = 0;
cout<<*p1;//0

空指针
空指针不指向任何对象,在试图使用一个指针之前代码可以首先检查它是否为空。以下是生成空指针的方法:

int *ptr1 = nullptr;  // C++11 使用空指针字面量生成空指针
int *ptr2 = 0;  // 传统C风格的空指针表示法
//需要事先#include <cstdlib>
int *ptr3 = NULL;  // 传统C风格的空指针表示法

注意:把int变量直接赋给指针是错误的,即使int变量的值恰好是0也不行:

int zoro = 0;
int *pi; 
pi = zero;

void *指针
void * 是一个特殊的指针类型,可以存放任意对象的地址,但不能直接操作void /*指针所指的对象,因为我们并不知道这个对象到底是什么类型,也就无法确定能在这个对象上做哪些操作。
指针比较
在条件表达式中,任何非0(非空)指针对应的条件值都是true。
对于两个类型相同的合法指针,如果两个指针存放的地址值相同,则他们相等。
地址值相同有以下三种:
1.他们都指向同一个对象。
2.他们都指向同一对象的下一个地址。
3.他们都为空。
注意:如果出现一个指针指向某对象,同时另一个指针指向另外对象的下一个地址,此时也可能这两个指针值相等的情况

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月落霜满天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值