CPP学习之——到底是使用引用还是指针(9.14-9.15)

一 概述

  • 既然引用实现了指针的功能,而且使用起来更加方便,为什么还要指针呢?
  • 这是因为指针可以为空,但是引用不能为空,指针可以被赋值,但是引用只可以被初始化,不可以被赋为另一个对象的别名。如果你想使一个变量记录不同对象的地址,那么就必须使用指针

二 错误示例

2.1 示例一

2.1.1 代码

1
2
3
4
int a=6;
int &p=a;
int b=9;
p=&b;//(错误位置)

2.1.2 代码说明

  • 由于引用只可以被初始化,不能被赋值,所以我们不能讲p再做为变量b的别名
  • 另外,在堆中创建一块内存区域,必须要用指针指向它,否则该区域就会变成无法访问的内存空间。当然我们也可以使用引用来应用指向内存空间的指针

2.2 示例二

2.2.1 代码

1
2
3
4
5
int *p=new int;
int &r=*p;
r=4;
cout<<*p<<endl;
cout<<r<<endl;

2.2.2 代码说明

  • 这样,这个r就变成了用指针p读取到的值的别名
  • 但是我们要明白一点,我们不可以直接用引用来指向堆中新建的空间,因为引用只是个别名,它不可以作为指针来使用

2.3 示例三

2.3.1 代码

1
int *&r=new int;(编译不通过)

2.3.3 代码说明

  • 因此在机器运行不正常的情况下,也就是机器虚拟机内存太小,无法创建新空间的情况下,那么new int会自动返回一个空指针。
  • 我们知道引用不能为空,因此这种情况下使用语句:int *&r=new int;会导致一个无用的别名。而使用星号(*)读取一个无用的别名则会引起系统奔溃

2.3.4 解决办法

  • 解决办法是不要将引用初始化为新建内存区域的别名,而要将r初始化为指向该区域的指针的别名。前提是首先要判断该指针不为空

三 代码及输出

3.1 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
#include<iostream>
using namespace std;
int main()
{
int *p=new int;
if(p!=NULL)
{
int &r=*p;
r=3;
cout<<r<<endl;
}
return 0;
}

3.2 输出结果

1
3

3.3 说明

  • 假如不为空,将r初始化为指针p的别名,或者指针p指向的数据的别名
  • int *p=new int;第一行定义了一个指向int的指针p,该指针指向新建的一块内存
  • if(p!=NULL);第二行测试p,假如不为空,表示空间创建成功
  • int &r=*p;将r初始化为p指向的内存空间中数据的别名
  • r=3;然后通过r将3保存在该空间中,接着输出该空间的值

四 总结

指针与引用的区别:

  • 指针可以为空,引用不能为空
  • 指针可以被赋值,引用不能被赋值
  • 指针可以指向堆中空间,引用不可以指向堆中空间

了解了引用和指针的区别,我们就可以有选择的使用指针或者引用了

五 别名和指针混合使用

5.1 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<iostream>
using namespace std;
int *func(int &one,int *two,int x);
int main()
{
int num=3;
int &mum=num; //定义num的别名mum
int *two=&num;
num=3;
int x=3;
cout<<func(mum,two,x);
return 0;
}
int *func(int &one,int *two,int x)
{
return two;
}

5.2 代码说明

  • 该行语句声明了一个func函数,该函数有三个参数,第一个是int型变量的别名one,第二个是指向int型变量的指针two,第三个是整型参数X。该函数返回一个指向int型变量的指针