C++:引用

 

目录

概念:

引用的使用格式:

引用特性:

常引用

 使用场景:

1、做参数

二级指针时的取别名 

一级指针取别名

一般函数取别名

2、做返回值

 函数返回值的原理:

引用的返回值使用:

引用和指针的对比: 

 语法层面:

底层:

概念:

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空 间,它和它引用的变量共用同一块内存空间。

int main()
{int a=0;// 引用,b就是a的别名int& b= a;cout <<&b<< endl;cout<< &a<< endl;return 0;
}

如上代码所示,引用符是&,但是要和C语言中的&区分,如上代码就第一个&是c++的,而第二个是C语言的 ,且我们开辟了一个空间,它叫做a ,同时他又叫做b,二者的空间地址都是一样的。

取别名的同时还可以给别名取别名!这就相当于把李逵叫铁牛的同时,又把李逵叫做黑旋风。

int main()
{int a=0;// 引用,b就是a的别名int& b= a;cout <<&b<< endl;cout<< &a<< endl;int& c= a;//给别名取别名,如给别名b取了个别名叫做dint& d= b;return 0;
}

引用的使用格式:

类型& 引用变量名(对象名) = 引用实体;

void TestRef()
{int a = 10;int& ra = a;//<====定义引用类型printf("%p\n", &a);printf("%p\n", &ra);
}

注意:引用类型必须和引用实体是同种类型的。 

引用特性:

  1. 引用在定义时必须初始化
  2. 一个变量可以有多个引用
  3. 引用一旦引用一个实体,再不能引用其他实体 

 最重要的是第三点!第三点通俗来讲就是,当一个空间A取了一个别名X,那么另一个空间B就不能取和A空间相同名字的别名,也就说空间B的别名不能取X。

1、引用必须初始化int& b;//没有初始化,是错误的
b=c;2、引用定义后,不能改变指向int& b= a;
int c=2; 
b=c; //本意是相将c取一个别名,但是这个意思只有赋值的意思,这是常见错误!//且不能同时取一样名字的别名

常引用

关于常引用,当变量的前方加上了const 后,该变量就变成了常量,而对于常量而言,不论是加上了const的变量变成的,还是本身就是一个常量数值,它在引用时必须要加上const ,此外因为引用类型必须和引用实体是同种类型的,但是如果想要跨越类型引用,也必须加上const!

void TestConstRef()
{const int a = 10;//int& ra = a;   // 该语句编译时会出错,a为常量const int& ra = a;// int& b = 10; // 该语句编译时会出错,b为常量const int& b = 10;double d = 12.34;//int& rd = d; // 该语句编译时会出错,类型不同const int& rd = d;
}

 使用场景:

1、做参数

  • 当引用使用在函数的参数上时,引用的用法就和指针一样,指针是因为C语言的形参只是拷贝,所以在传参时需要传递数值的地址,并且需要使用指针来存储地址并指向地址。
  • 而引用是给变量取别名,空间地址是不变的,所以传递参数并且给它取了个别名使用和指针的用法是一样的!

二级指针时的取别名 

//* & phead 是指给传过来的指针取了别名进行下面的函数使用void PushBack(struct Node*& phead,int x)
{phead = newnode;
}int main(){struct Node* plist = NULL;return 0;}

一级指针取别名

void PushBack(struct pNode& phead,int x)
{phead = newnode;
}int main(){pNode plist = NULL;return 0;}

一般函数取别名

void Swap(int& a,int& b)
{//...
}
int main()
{int x=0,y=1;Swap(x,y);return 0;
}

2、做返回值

 函数返回值的原理:

  • 如下图所示,在C语言中,ret 的值是调用了func函数,而func函数会返回一个a,但是按照函数栈帧来讲,mian空间里面开辟了一个空间,而func也开辟了空间。
  • 但是func的空间会随着的调用结束而销毁(作用域的生命周期),同时返回值a也在销毁的地方,所以相当于a销毁了,于是乎ret得到的是个不知道是什么的值。
  • 但是计算机也知道这个东西会这样的结果,所以a就会被计算机传到一个寄存器中,由寄存器保存并交给ret,所以ret拿到的是寄存器的地址和寄存器里面的东西。

引用的返回值使用:

引用的返回值必须使用在全局变量、静态变量、堆上变量否则会出问题。 

静态变量的 返回值的 引用使用方法 
//其中函数的前面是返回值的类型,而这里的返回类型是返回一个别名
//表示着返回了一个变量a的别名 aint& func()
{static int a = 0;return a;
}int main()
{int ret = func();cout << ret << endl;return 0;
}

 如果,返回值并未在上述中的区域出现,且贸然的使用引用,那么根据函数返回值的原理,主函数main 中的变量拿到的这个返回值是已经因为生命周期消失而消失的数值和地址,这个是不成立且得到的数值是随机性的!

就比如下面代码中的ret一样,拿到的并非是寄存器的地址和里面的数值,而是消失的空间地址和里面的数值,就和野指针一样,是一个“野别名”

错误示范!int& func()
{int a = 0;return a;
}int main()
{int ret = func();cout << ret << endl;return 0;
}

引用和指针的对比: 

 语法层面:

  1. 引用是别名,不开空间,指针是地址,需要开空间存地址
  2. 引用必须初始化,指针可以初始化也可以不初始化
  3. 引用不能改变指向,指针可以
  4. 引用相对更安全,没有空引用,但是有空指针,容易出现野指针,但是不容易出现野引用
  5. 在sizeof中含义不同:引用结果为引用类型的大小(如int&、double&等),但指针始终是地址空间所占字节个数(32 位平台下占4个字节)

底层:

  • 汇编层面上,没有引用,都是指针,引用编译后也转换成指针了
  • 在底层代码中,引用其实就是指针,或者说引用会转化为指针并且开辟空间 


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/650713.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java Swing桌面项目打包成可执行jar

前言 最近有需求&#xff0c;将Swing项目打包为一个可执行的jar包&#xff0c;遇见了一些问题&#xff0c;参考AI助手&#xff0c;解决了遇到的问题&#xff0c;也有一些亲身实践体会&#xff0c;记录一下。开发环境IntelliJ IDEA&#xff0c;JDK8&#xff0c;用kotlin语言实现…

navicat连接postgresql、人大金仓等数据库报错

navicat连接postgresql、人大金仓数据库报错问题是一个偶现的问题&#xff0c;需要我们特别关注&#xff1a; 1、客户端连接人大金仓数据库 这里注意&#xff1a;navicat连接postgresql、人大金仓数据库时均选择postgresql类型&#xff0c;因为人大金仓数据库底层和psql数据库…

【第五天】蓝桥杯备战

1、金币 https://www.lanqiao.cn/problems/357/learning/ 解法&#xff1a;暴力 import java.util.Scanner; // 1:无需package // 2: 类名必须Main, 不可修改public class Main {public static void main(String[] args) {Scanner scan new Scanner(System.in);//在此输入…

01_Anaconda环境搭建

概述 Anaconda包含了许多常用的科学计算和数据分析的库和工具。通过Anaconda&#xff0c;用户可以更方便地安装、管理和更新这些库和工具&#xff0c;从而提高工作效率。 Anaconda还提供了一个名为conda的包管理器&#xff0c;可以帮助用户方便地安装、管理和更新这些库和工具…

写静态页面——魅族声学_前端页面练习

1、效果: 1、html代码: <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>魅族声学</titl…

金智易表通构建学生缴费数据查询+帆软构建缴费大数据报表并整合到微服务

使用金智易表通挂接外部数据,快速建设查询类服务,本次构建学生欠费数据查询,共有3块设计,规划如下: 1、欠费明细查询:学校领导和财务处等部门可查询全校欠费学生明细数据;各二级学院教职工可查询本二级学院欠费学生明细数据。 2、大数据统计报表:从应收总额、欠费总额…

Spring与Redis集成

1.引入RedisTemplate 据以前的情况&#xff0c;我们在Java中使用Redis时一般是使用Jedis来操作的&#xff0c;大致的一段代码如下所示 Overridepublic User findUserById(Integer id) {User user null;Jedis jedis null;try {jedis jedisPool.getResource();String userStr…

直接在GitHub上使用vscode阅读源码

方法&#xff1a; 直接在github后面输入1s即可 效果&#xff1a;

光学系统的核心--分辨率

前言 在机器视觉领域&#xff0c;可以把各个部件划分为光源&#xff0c;镜头&#xff0c;相机&#xff0c;采集卡&#xff0c;算法&#xff0c;运动平台等。各个部件都是系统的有机组合&#xff0c;均有各自的重要性。在实际应用中&#xff0c;成像镜头涉及的光学理论较多&…

[数据结构]-哈希

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 本期学习目标&…

智能工厂4G无线设备预测维护云端联动的DI、AI、DO混合信号处理单元

在现代工业智能化进程中&#xff0c;一款集成了丰富I/O接口并能与各大云平台无缝对接的智能设备显得尤为重要。比如最近推出的这款创新产品&#xff0c;它集合了8路数字输入通道&#xff0c;涵盖了干湿节点的识别功能&#xff0c;适用于多种开关量信号的读取&#xff1b;同时&a…

(八)springboot实战——springboot3下的webflux项目全局异常处理

前言 在webflux响应式编程中&#xff0c;如何处理系统运行时异常是本节的主要内容。在传统的Servlet阻塞式web项目中主要通过HandlerExceptionResolver处理器来处理&#xff0c;而在webflux响应式web项目中&#xff0c;则是通过DispatchExceptionHandler异常处理器来处理异常。…

[SWPUCTF 2018]SimplePHP1

打开环境 有查看文件跟上传文件&#xff0c;查看文件里面显示没有文件url貌似可以文件读取 上传文件里面可以上传文件。 先看一下可不可以文件读取 /etc/passwd不能读取&#xff0c;源码提示flag在f1ag.php 看看能不能读取当前的文件&#xff0c; 先把代码摘下来 file.php …

JavaScript 之 作用域变量提升闭包

一、JavaScript 代码的执行 浏览器内核是由两部分组成的&#xff0c;以 webkit 为例 WebCore&#xff1a;负责HTML解析、布局、渲染等等相关的工作JavaScriptCore&#xff1a;解析、执行 JavaScript 代码 另外一个强大的 JavaScript 引擎就是 V8 引擎 二、深入 V8 引擎原理 …

Java面向对象三大特征之多态

在之前的文章&#xff0c;我们分别介绍了类与对象、面向对象三大特征的封装、以及继承&#xff08;一&#xff09;、继承&#xff08;二&#xff09;。这一篇文章&#xff0c;我们介绍Java面向对象三大特征的最后一个——多态。 多态 多态的概述 概念&#xff1a;完成某个行为…

CVE-2024-23897 Jenkins 任意文件读取漏洞

项目介绍 Jenkins是一个开源软件项目&#xff0c;是基于Java开发的一种持续集成工具&#xff0c;用于监控持续重复的工作&#xff0c;旨在提供一个开放易用的软件平台&#xff0c;使软件项目可以进行持续集成。Jenkins是开源CI&CD软件领导者&#xff0c; 提供超过1000个插…

Java集合相关面试题

&#x1f4d5;作者简介&#xff1a; 过去日记&#xff0c;致力于Java、GoLang,Rust等多种编程语言&#xff0c;热爱技术&#xff0c;喜欢游戏的博主。 &#x1f4d7;本文收录于java面试题系列&#xff0c;大家有兴趣的可以看一看 &#x1f4d8;相关专栏Rust初阶教程、go语言基…

C# 设置一个定时器函数

C#中&#xff0c;创建设置一个定时器&#xff0c;能够定时中断执行特定操作&#xff0c;可以用于发送心跳、正计时和倒计时等。 本文对C#的定时器简单封装一下&#xff0c;哎&#xff0c;以方便定时器的创建。 定义 using Timer System.Timers.Timer;class SetTimer {Timer …

OSPF协议基础(OSPF工作过程)

目录 OSPF基本工作原理邻居建立过程Router ID发现并建立邻居 - Hello报文OSPF邻居建立过程 链路状态信息丰富的数据链路层支持能力网络类型 - P2P网络网络类型 - 广播型网络网络类型 - NBMA网络网络类型 - P2MP网络OSPF的度量方式 报文类型及作用OSPF协议报文头部OSPF报文类型O…

k8s-调度

调度 从上面的架构图我们可以看到,调度是工作在Master,负责调度Pod&#xff0c;为POD分配Node。 调度的工作原理 #查看所有的Node kubectl get nodes 我们可以看到节点有一个Name,这就是调度的关键。 调度的步骤&#xff1a; 1 创建POD的时候每一个POD都会有一个叫NodeName的…