浅析C++中引用与指针的区别

article/2025/9/20 19:34:10

引用和指针的概念及区别

  • 1. 引用及指针概念
    • 1.1 指针概念
    • 1.2 引用概念
  • 2. 引用与指针的区别

1. 引用及指针概念

如果熟悉指针和引用的使用,应该能感觉到指针和引用在很多场景使用起来还是有很大的相似性的,尽管它们在语法层面上是俩个完全不同的概念。
那么这二者之间到底具有怎样的相似性以及又有什么样的区别呢?这篇文章就和大家一起来探讨一下这俩个问题。

在谈这个话题之前我们先简单回顾一下指针和引用的概念:

1.1 指针概念

在计算机科学中,指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向(points to)存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“指针”。 意思是通过它能找到以它为地址的内存单元。

也就是说,“指针”是一个地址,变量的指针就是变量的地址。而我们通常所谈的“指针”,其实是 “指针变量”,它的概念是存放着地址的变量。“指针”和“指针变量”实际上是俩个不同的概念,但我们在日常的学习和使用中,经常把“指针变量”简称为“指针”,因此,作为使用者的我们,一定要能够在心中区分这俩个不同的概念,以免混淆。

我们这里所谈的指针,正是指针变量,用来存放地址, 地址唯一标识一块内存空间。也就是说,指针(变量)保存着其所指向对象的地址。因此,对指针的操作,也可以联系到其所指向的变量。如以下代码:

int main()
{int a = 10;int *pa = &a; //定义指针变量pa,指向整形变量a*pa = 20; //通过指针的解引用操作修改a的值cout << "a = " << a << endl;return 0;
}

1.2 引用概念

通过上述对指针概念的回顾我们可以知道,指针其实是一个变量,既然是变量,就会占据一定的内存空间。 而现在要谈的引用,并不是定义一个新的变量,而是给一个已经存在的变量取一个“别名”, 编译器不会为引用开辟内存空间,它和它所引用的变量共用一块内存空间。
比如说,我的一位高中同学有一个外号叫“二狗”,我们一般不喊的真名,只需要喊他“二狗”,他就知道我们是在叫他,并给予我们回应。
在这里插入图片描述
也就是说,引用其实就是其所指向的实体本身, 就像“二狗”就是我那个同学本人,只不过是另一个名字(外号)罢了。

定义引用类型的方式与定义指针变量的方式类似,一般形式为:
类型 &引用变量名(对象名) = 引用实体;

int main()
{int a = 10;int &ra = a; //定义引用类型ra = 20; //通过引用修改a的值cout << "a = " << a << endl; //20cout << "ra = " << ra << endl; //20return 0;
}

2. 引用与指针的区别

通过上述概念回顾,我们初步感受到其实指针和引用在使用上是有一定的相似性的, 比如二者都可以代表其所指向或者所引用的变量,并能够通过指针或者引用来修改他们联系的对象。
甚至有一个结论说出来可能还有读者会感到震惊:
在底层实现上,引用和指针甚至没有任何区别,引用就是指针!
可是口说无凭啊,这篇文章谈的不就是指针和引用的区别吗,看到这才感觉重点要来了,你却说指针和引用是一样的?证据呢?
首先要说一句这并不是在开玩笑,至于原因,大家往下看:

int main()
{int a = 10;int *pa = &a;*pa = 20;int &ra = a;ra = 20;return 0;
}

通过VS2013下的监视窗口,我们来观察一下这段代码的反汇编指令
在这里插入图片描述
看到上图,尽管我们可能看不懂汇编代码,但我们却能看出二者在底层实现上的确是没有什么区别的,毕竟一模一样的汇编代码足以说明问题。也就是说,引用的底层其实就是按照指针的方式来实现的,在底层实现上引用其实也是有空间的。

如果觉得仅仅上边一个例子还不足以说明问题,那么大家下去可以自行多加尝试,比如观察分别以引用和指针变量作为形参的函数汇编代码的对比,看看是否依然相同。这个问题这里就不在过多赘述。

但在日常学习和使用中,我们更关心的其实是二者在语法概念上的区别,毕竟我们只是使用者,至于它们在底层究竟是如何实现的,大多数情况下我们并不关心。理解指针和引用在语法概念上的区别, 才是我们着重需要考虑的。

总体来说,指针和引用主要有以下几个方面的不同点:

1. 引用在定义时必须初始化,而指针没有要求

int main()
{int a = 10;//int &ra; //会报错,引用在定义时必须同时进行初始化int &ra = a; //正确的定义方式int *p; //定义时可以不初始化return 0;
}

2. 用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体

int main()
{int a = 10;int b = 20;int &ra = a;//&ra = b; //会报错,引用一旦定义,不能在引用其他实体//ra = b; //不会报错,但这条语句的意思是将b的值赋给ra(a),并不是引用其他实体int *pa = &a;pa = &b; //正确,修改pa的指向,使其指向变量breturn 0;
}

3. 指针有空值NULL,但引用没有NULL引用这一说

int *p = NULL; //正确,初始化指针变量p为NULL
int &r = NULL; //错误,没有NULL引用

4. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)

int main()
{char c = 'a';char *pc = &c;char &rc = c;cout << "sizeof(pc) = " << sizeof(pc) << endl; //4cout << "sizeof(rc) = " << sizeof(rc) << endl; //1return 0;
}

5. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小

 int main()
{int arr[] = { 1, 3, 5, 7 };int *p = &arr[0];p++;//指向下一个元素cout << "*p = " << *p << endl; //3int &r = arr[0];r++; //其引用的实体自加1,即arr[0] = arr[0] + 1cout << "r = " << r << endl; //2cout << "arr[0] = " << arr[0] << endl; //同上return 0;
}

7. 有多级指针,但是没有多级引用

int main()
{int a = 10;int *pa = &a; //定义一级指针,指向一个同类型变量int **ppa = &pa; //定义二级指针,指向一个一级指针int &ra = a; //定义引用//int &&rra = ra; //错误,没有多级引用return 0;
}

8. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理

int main()
{int a = 10;int b = 20;int *pa = &a;*pa = 30; //通过解引用操作修改a的值cout << "a = " << *pa << endl; //通过解引用打印a的值(30)int &rb = b;rb = 40; //通过引用直接修改b的值cout << "b = " << rb << endl; //通过引用直接打印b值(40)return 0;
}

9. 引用比指针使用起来相对更安全 :

比如使用指针可能会出现野指针的情况,如果操作失误,可能会访问不合法的空间,造成我们不想看到的后果,但引用不会。并且引用一旦定义, 即与当前所引用实体绑定,不能再引用其他实体, 这个规则一定程度上也使得引用在使用时更加安全。

没有提到的相关内容欢迎大家补充交流!


http://chatgpt.dhexx.cn/article/y0mNm7qM.shtml

相关文章

C语言-引用和指针的区别?

①引用的格式&#xff1a;数据类型 &引用名 变量名&#xff1b; 指针的格式&#xff1a;数据类型 *变量名指向的变量地址&#xff1b;②使用引用一定要进行初始化 指针为了不出现野指针&#xff0c;也要进行初始化为NULL ③引用只能对数组的元素使用&#xff0c;不能对整个…

c++引用与指针的区别

目录 一、从语法上来讲 二、从汇编层面来看 一、从语法上来讲 1.指针是存储某个实例的地址&#xff0c;引用是实例的别名 2.程序为指针分配内存区域&#xff0c;而不为引用分配内存区域 3.指针使用时要加 “ * ”&#xff0c;解引用&#xff0c;引用可以直接使用 例&…

C++引用和指针的区别

作者&#xff1a;RainMan 链接&#xff1a;https://www.zhihu.com/question/37608201/answer/545635054 来源&#xff1a;知乎 著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。 引用是C引入的重要机制&#xff08;C语言没有引用&#xff0…

引用和指针的区别

引用和指针的区别: C的引用(Reference) 1.定义引用就是给某个变量起别名&#xff0c;对引用的操作和对该变量操作完全相同。 int a 10&#xff1b; int& b a;//b就是a的别名 b; cout << a << endl;//11 2 常引用 1&#xff09;定义引用时加const修饰&#…

C++中引用和指针的区别

下面用通俗易懂的话来概述一下&#xff1a; 指针-对于一个类型T&#xff0c;T*就是指向T的指针类型&#xff0c;也即一个T*类型的变量能够保存一个T对象的地址&#xff0c;而类型T是可以加一些限定词的&#xff0c;如const、volatile等等。见下图&#xff0c;所示指针的含义&am…

C/C++引用和指针的区别

为什么C/C语言使用指针&#xff1f; 答案&#xff1a;①一方面&#xff0c;每一种编程语言都使用指针。不止C/C使用指针。 每一种编程语言都使用指针。C将指针暴露给了用户(程序员)&#xff0c;而Java和C#等语言则将指针隐藏起来了。 “Everything uses pointers. C just expo…

C++ 引用详解(引用的特点,引用与指针的区别,引用的其他使用)

目录 引用一.引入</font>二.C中较为麻烦的运算符</font>三.引用的定义</font>四.引用的特点五.对比指针与引用六.引用与指针的区别&#xff08;重点&#xff09;1.语法层面的区别2.汇编层面的区别 七.引用的其他使用 引用 一.引入 在生活中&#xff0c;我们…

Zipkin和Sleuth

“sleuth的作用是在系统中自动埋点并把数据发送给zipkin,zipkin的作用是存储这些数据并展现。” 说白了 sleuth就是为了Zipkin服务的 看了一圈 总结一下 就是微服务的链路追踪 我们看这个延迟的时间可以判断哪个服务出现了问题 进而排查出问题 简单说&#xff1a;假如服务 …

spring-cloud-sleuth分布服务跟踪式

why: 1,微服务架构微服务增多&#xff0c;一个客户端请求形成一个复杂的分布式服务调用链路&#xff0c;如果任何一个服务延迟过高或错误&#xff0c;都会引起请求失败。 how&#xff1a; 先引入了example&#xff1a; https://github.com/spring-cloud/spring-cloud-sleuth 1…

笔记:Sleuth 的底层逻辑

Sleuth 是通过打入到 Log 中的“卧底”来串联前后日志的。你集成了 Sleuth 组件之后&#xff0c; 它会向你的日志中打入三个“特殊标记”&#xff0c;其中一个标记你应该已经清楚了&#xff0c;那便是 Trace ID。剩下的两个标记分别是 Span ID 和 Parent Span ID&#xff0c;…

sleuth介绍

spring Cloud Sleuth为 spring Cloud提供了分布式跟踪的解决方案&#xff0c;它大量借用了Google Dapper、 Twitter Zipkin和 Apache HTrace的设计&#xff0c;先来了解一下 Sleuth的术语&#xff0c; Sleuth借用了 Dapper的术语。 span&#xff08;跨度&#xff09;&#xff…

sleuth 链路追踪

一&#xff1a;什么是链路追踪 对于以前的单服务器项目而言&#xff0c;如果一个地方出了问题&#xff0c;很容易去找到。可是对于微服务架构项目来说&#xff0c;因为微服务太多&#xff0c;而且往往是一个微服务调用了很多其他的微服务&#xff0c;如果一个地方出错&#xff…

java sleuth配置

java sleuth配置 springCloud学习记录SpringCloud Alibaba sleuth&#xff08;分布式请求链路跟踪&#xff09;zipkinsleuthpomyml springCloud学习记录 SpringCloud Alibaba sleuth&#xff08;分布式请求链路跟踪&#xff09; 在微服务框架种&#xff0c;一个由客户端发起的…

Spring Cloud Sleuth+Zipkin 构建微服务链路跟踪系统

什么是链路跟踪系统&#xff1f; 在微服务中&#xff0c;多个服务分布在不同物理机器上&#xff0c;各个服务之间相互调用。如何清晰地记录服务调用过程&#xff0c;并在出现问题的时候能够通过查看日志和服务之间的调用关系来定位问题&#xff0c;这样的系统就叫做链路跟踪系…

SpringCloud Sleuth入门介绍

案例代码:https://github.com/q279583842q/springcloud-e-book 一、Sleuth介绍 为什么要使用微服务跟踪?它解决了什么问题&#xff1f; 1.微服务的现状&#xff1f; 微服务的现状   随着业务的发展&#xff0c;单体架构变为微服务架构&#xff0c;并且系统规模也变得越来…

Spring Cloud Sleuth HTTP详解

目录 1版本关系 2简介 2.1术语 2.2调用链可视化 2.2.1使用Zipkin进行分布式跟踪 2.2.2错误可视化 2.2.3使用Brave进行分布式跟踪 2.2.4将Sleuth添加到项目中 3调用信息生成与上报原理 3.1初始化配置类 3.2过滤器-请求过滤 3.3调用信息拦截 3.4调用信息上报 4日志…

Sleuth链路追踪

文章目录 Spring-Cloud-Alibaba-Sleuth链路追踪一、链路追踪介绍二、Sleuth入门演示&#xff1a; 三、ZipKin介绍ZipKin服务端安装ZipKin数据持久化 Spring-Cloud-Alibaba-Sleuth链路追踪 一、链路追踪介绍 在大型的微服务项目中&#xff0c;一个系统被拆分成许多模块&#xf…

sleuth原理详解

sleuth原理 1、关键术语 Span&#xff1a;Span基本工作单元&#xff0c;发送一个远程调度任务就会产生一个Span, Span 是用 64ID唯一标识的&#xff0c;Trace是用另一个64ID唯一标识的。Span还包含了其他的信息&#xff0c;例如摘要、时间戳事件、Span的ID以及进程 ID。Trace…

07-搭建微服务-链路追踪Sleuth

1、为什么使用链路追踪&#xff1f; 在微服务中&#xff0c;随着服务越来越多&#xff0c;对调用链的分析越来越复杂。 出现问题&#xff1a; 1、微服务之间的调用错综复杂&#xff0c;用户发送的请求经历哪些服务&#xff0c;调用链不清楚&#xff0c;没有一个自动化的工具类来…

sleuth入门

Sleuth介绍 SpringCloud Sleuth主要功能就是在分布式系统中提供追踪解决方案。它大量借用了Google Dapper的设计&#xff0c; 先来了解一下Sleuth中的术语和相关概念。 Trace 由一组Trace Id&#xff08;贯穿整个链路&#xff09;相同的Span串联形成一个树状结构。为了实现请求…