指针和引用的区别

概念:

指针就是一个变量的地址,本质上也是一个变量,可以对指针取地址也就是说存在多级指针。
引用就是一个变量的别名,与被引用的变量共享同一块内存空间。不能对一个引用取引用也就是不存在多级引用。
 

#include <iostream>
using namespace std;

int main()
{
	int a = 1;
	int* pa = &a; // 变量的地址,本质是一个变量
	int** ppa = &pa; // 可以对指针取地址,此时得到的是一个二级指针

	int& b = a; // 变量的别名,与a共享同一块内存空间
	int& c = &b; // 不存在多级引用

	return 0;
}

在这段代码里面,我们定义了一个变量a,我们对变量a取地址初始化了指针变量pa,那么pa就是a的地址,由于pa本身也是一个变量所以我们可以对它取地址初始化给一个二级指针ppa。但是由于引用本身不是变量,只是一个别名,所以不存在多级引用。

大小:

指针的大小只与操作系统的位数有关与指针的类型无关。32位是4个字节,64位是8个字节。
引用的大小是被引用的变量的大小。

在第一张图片种由于红框框里的是x64(64位),所以不管指针的类型通过sizeof计算出来的大小永远都是4个字节。在第二张图片中由于红框框里的是x86(32位),所以不管指针的类型通过sizeof计算出来的大小永远都是8个字节。其实这里有个小技巧,指针大小=操作系统位数(64位或32位)/一个字节的位数(8字节)=4或8。

安全性:

指针不安全,可能会出现悬空指针、野指针、悬空指针。
引用安全,引用必须初始化,不会出现不安全的引用或者空引用。

上图中,p1定义时初始化为nullptr,产生了空指针,对一个空指针解引用就会产生未定义行为;p2定义但是没有初始化产生了野指针,对一个野指针解引用也会产生未定义行为;对于p3最开始指向了一块内存足够内存存放的值是1,但是释放这块内存的时候没有将p3置空,就会产生悬空指针,对一个悬空指针解引用也是一个未定义行为。

参数传递/返回值传递:

我们知道在进行参数传递或者返回一个对象的时候(C++其实对于对象跟变量不怎么区分了,变量可以理解为)尽量去传它的地址或者返回它的地址,由于引用底层也是一根指针,所以从计算机的角度来讲他们的开销是一样的,但是从用户的角度来讲使用会更加方便。

我们先来看参数传递:

#include <iostream>
using namespace std;

class A
{
public:
	A()
	{

	}
	~A()
	{

	}
private:
	int* pa_ = new int[5] {1, 2, 3, 4, 5};
};
void show(A& a)
{
	A b;
	a = b; // 直接使用即可,不需要解引用
} // 1

void show(A* pa)
{
	A b;
	*pa = b; // 需要解引用才可以被赋值
} // 2
int main()
{
	A a;
	show(a); // 对于引用传递只需要传递对象本身,最终会走到1
	show(&a); // 对于指针传递需要传递对象的地址,最终会走到2
	return 0;
}

在以上代码中,main函数里我们先定义了一个对象a,由于对象占用的内存比较大我们想传一个地址给形式参数,我们可以传递指针或者传递引用,那我们传递指针好还是传递引用好呢?在show(a)里我们传递的是引用,对于调用方我们只需要传递对象,不需要传对象的地址,对于函数体里我们可以直接使用对象,不需要对其解引用,我们在定义传引用的函数时注意在类型后面加一个取引用符&,其实这跟我们在定义引用的时候是一样的,其实这里只是做了一个引用的初始化,相当于A&a = a;(为什么这里名字一样也可以?因为作用域不同,所以名字不一样也可以)。但是传指针我们在调用函数的时候需要对对象取地址,在定义这个传递指针的函数的时候需要定义指针来接收,相当于int*a = &a,在使用这个指针a的时候还需要解引用,所以相对于传递引用来讲会更加麻烦。其实不管是指针传递还是引用传递他们传递都是地址,底层汇编指令也是一样的。如下图:

怎么查看汇编指令?

先点运行,然后右键你想查看的代码对应的汇编指令,然后点击反汇编。如图所示步骤:

返回值传递同理,对于指针我们需要返回一个对象的地址,但是对于引用我们只需要返回对象本身。

ok,本文分别从概念、大小、安全性、参数传递/返回值传递四个角度去简单介绍了指针和引用的区别,因为我们本篇文章的重点是介绍指针和引用的区别,所以里面很多的细节没有涉及到,比如在传参的过程中暴露了地址给形参,那么形参不小心改了导致实参也改了怎么办,再比如说局部对象出栈销毁,那返回的地址不就是无效地址了吗,这样还可以返回吗,对于这些问题我们会在以后的专题里面逐步讲解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值