C++11笔记(3)——引用&指针辨析

变量和基本类型——引用和指针辨析

引用为对象起了另外一个名字,引用必须被初始化,引用本身不是一个对象,所以不能定义引用的引用。

int ival = 1024;
int &refVal = ival;	//refVal指向ival(是ival的别名)
int &refVal2;	//报错:引用必须被初始化
refVal = 2;	   //把2赋给了refVal所指向的对象,即ival
int ii = refVal;	//与ii = ival执行结果一样

引用的类型一般(有例外后面再说)都要和与之绑定的对象严格匹配。而且,引用只能绑定在对象上,不能与字面值或某个表达式的计算结果绑定在一起:

int &refVal3 = 10;		//错误:引用类型的初始值必须是一个对象
double dval = 3.14;
int &refVal4 = dval;	//错误:此处引用类型初始值必须是int型对象

一旦定义了引用,就无法令其再绑定到另外的对象,引用是“从一而终”的。

指针:与引用类似,指针也实现了对其他对象的间接访问。两者不同点:**一、**指针本身就是一个对象,允许对指针进行赋值和拷贝,而且在指针的生命周期内它可以先后指向几个不同对象。二、指针无需在定义时赋初值。和其他内置类型一样,指针如果没有被初始化,将拥有一个不确定的值。
指针存放的是某个对象的地址,想获取该地址用
取地址符
(&)。

int *p1, *p2;	//p1 p2都是指向int型对象的指针
int ival = 42;
int *p = &ival;	   //p存放ival的“地址”,或说p是指向变量ival的指针
int *p2 = p;	//初始值是指向int对象的“指针”
int *p3 = nullptr;		//空指针,等价于int *p3 = 0
int *p4 = NULL;		//空指针,与上类似
cout<< *p <<endl;	//输出42,解引用符*访问该对象

因为引用不是对象,没有实际地址,所以不能定义指向引用的指针。
指针的值(即地址)应属于下列4中状态之一:

  1. 指向一个对象。
  2. 指向紧邻对象所占空间下一位置。
  3. 空指针,意味着指针没有指向任何对象。
  4. 无效指针,也就是上述情况外的其他值。

在声明语句中(等号左边),&和*用于组成复合类型;在表达式中(等号右边),它们角色又变成运算符。
得到空指针最直接的办法是用字面值nullptr初始化指针,这也是c++11标准引入的方法。过去还会用到一个名为NULL的预处理变量给指针赋值,在头文件cstdlib中定义,值就是0;现在最好用nullptr,同时尽量避免使用NULL。
有时候想搞清楚一条赋值语句到底是改变了指针的值还是改变了指针所指向的对象的值不太容易,最好的办法就是记住赋值永远改变的是等号左侧对象。

pi = &ival;		//pi值被改变,现在pi指向ival】
*pi = 0;		//pi指向对象的值改变

对于两个类型相同的合法指针相比较,用==或!=比较,返回布尔类型。如果两指针存放的地址值相同,则相等。两个指针相等有三种情况:一、都为空;二、都指向同一对象;三、都指向了同一对象的下一地址。需要注意的是,如果一个指针指向某对象,同时另一个指针指向另外一个对象的下一地址,此时也有可能出现两指针相等的情况。
图片1

指向指针的指针
通过的个数可以区分指针的级别, **表示指向指针的指针

int ival = 1024;
int *p1 = &ival;	//p1指向int对象
int **p2 = &p1;		//p2指向一个int指针
cout<< *p1 <<endl;
cout<< **p2 <<endl;		//两次解引用

引用本身不是一个对象,因此不能定义指向引用的指针。但指针是对象,存在对指针的引用:

int i = 42;
int *p;		//p是一个int指针
int *&r = p;	//r是一个对指针p的引用,注意与int &r = p区别(因为引用两边类型要一致)

r = &i;		//r引用了一个指针,因此给r赋值&i就是令p指向i
*r = 0;		//解引用r得到i,也就是令p指向的对象,将i的值改为0
r = i;		//给r赋值i就是令p指向以i为地址的对象

要理解r的类型到底是什么,最简单办法是从右向左阅读r定义(int *&r = p;)离变量名最近的符号(此例中是&r的符号&)对变量的类型有最直接的影响,因此r是一个引用。声明符的其余部分用以确认r引用的类型是什么,此例中的符号*说明r引用的是一个指针。最后,声明的基本类型部分指出r引用的是一个int指针。

指针常量与常量指针

// 指针常量:const靠近*,指针不能变,即地址不能变,地址中保存内容可以变
int a, b;
int * const pInt = &a;
*pInt = 10;	// ok
pInt = &b;		// error!

// 常量指针:const靠近int,内容不能变,地址可以变
const int * pInt = &a;
*pInt = 10;	// error!
pInt = &b;		// ok

// 从左到右: const -> * -> const,指向常量的指针常量,地址和内容均不能变化
int a = 10;
const int * const pInt = &a;

快速记忆方法:

**1、先把double *ptr写好。三种方法中,double *ptr这三者顺序是不变的。
2、const double *ptr; // const读作常量,*读作指针,按顺序读为常量指针。
3、double const *ptr; // const读作常量,读作指针,按顺序为常量指针。
4、double * const ptr; // 读作指针,const读作常量,按顺序为指针常量。
5、const靠近
还是double,谁就是不变的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

幻欢子

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

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

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

打赏作者

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

抵扣说明:

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

余额充值