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.hqwc.cn/news/434060.html

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

相关文章

编码神仙插件Machinet AI GPT-4 Chat and Unit Tests

最近发现一个神仙插件Machinet AI GPT-4 Chat and Unit Tests&#xff0c;支持多个编译器安装使用。 我下载安装到Android Studio上&#xff0c;不需要登录直接可以使用。 可以直接提问&#xff0c;支持中文。

Socket实现模拟TCP通信粘包问题

在计算机网络通信中&#xff0c;粘包是指在传输过程中&#xff0c;发送方发送的多个小数据包被接收方粘合在一起&#xff0c;形成一个大的数据包。这种现象通常出现在使用流式传输协议&#xff08;如TCP&#xff09;进行数据传输的情况下。 具体来说&#xff0c;TCP是一种面向连…

将视频做成GIF动图

对于我们这种 做博客的人来说 掌握做gif图片 还是比较重要的一个技能 我们先准备一个剪辑好的视频 访问网址 https://ezgif.com/ 进入后 选择 Video to GIF converter 视频转GIF 点击下图指向出 选择文件操作 在弹出的选择目录中 找到我们的视频 然后选择 点击下方打开 它…

【开源】基于JAVA的毕业生追踪系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 登陆注册模块2.2 学生基本配置模块2.3 就业状况模块2.4 学历深造模块2.5 信息汇总分析模块2.6 校友论坛模块 三、系统设计3.1 用例设计3.2 实体设计 四、系统展示五、核心代码5.1 查询我的就业状况5.2 初始化就业状况5.…

1949-2022年交通运输设备行业数据

1949-2022年交通运输设备行业数据 1、时间1949-2021年 2、指标&#xff1a;民用驳船保有量(艘)_AmoCivBar、民用机动船保有量(艘)_AmoCivMotBoat、民用运输机保有量(架)_AmoPlaTra、民用其他汽车保有量(万辆)_AmoOthAutCiv、私人其他汽车保有量(万辆)_AmoOthAutPri、新注册民…

C++中map和set的使用

&#xff08;图片来源于网络&#xff09; &#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;强烈推荐优质专栏: &#x1f354;&#x1f35f;&#x1f32f;C的世界(持续更新中) &#x1f43b;推荐专栏1: &#x1f354;&#x1f35f;&#x1f32f;C语言初阶…

ASP.NET 7 Core Web 读取appsetting.json

把一些配置信息保存在json文件可以避免更改时要重新发布程序的烦恼。 我这里使用的是写一个类文件&#xff0c;然后通过program.cs启动的方式&#xff08;.net 6 开始没有startup了&#xff09;。 项目类型&#xff1a;ASP.NET Core Web MVC / .NET 7.0 / VS2022 第一步…

深度强化学习(王树森)笔记02

深度强化学习&#xff08;DRL&#xff09; 本文是学习笔记&#xff0c;如有侵权&#xff0c;请联系删除。本文在ChatGPT辅助下完成。 参考链接 Deep Reinforcement Learning官方链接&#xff1a;https://github.com/wangshusen/DRL 源代码链接&#xff1a;https://github.c…

移动端应用(APP)如何设计测试用例?

为 APP 设计测试用例需要考虑移动设备的特殊性&#xff0c;如不同的操作系统、设备尺寸、硬件特性以及应用程序自身的特定功能。 以下是为APP设计测试用例时要考虑的内容&#xff1a; 1. 理解需求 熟悉APP的功能需求、用户故事和设计文档。 确定APP的目标用户群体、使用场景…

教你打造专业的网络主播,主播与直播的培训教程合集

一、教程描述 本套教程可以让你快速上手&#xff0c;将你打造成一名有格调的网络主播&#xff0c;若是自己去摸索尝试&#xff0c;不仅浪费时间&#xff0c;而且进度还慢&#xff0c;最后效果也不一定很好。本套主播教程&#xff0c;大小8.43G&#xff0c;共有494个文件。 二…

JVM锁的膨胀升级过程详解

在Java虚拟机&#xff08;JVM&#xff09;中&#xff0c;锁是多线程编程的关键部分&#xff0c;用于保护共享资源&#xff0c;防止并发访问导致的数据不一致性。锁的性能和效率在高并发场景下至关重要。当多个线程竞争同一资源时&#xff0c;锁的状态可能会经历多次升级&#x…

Docker深入解析:从基础到实践

Docker基础知识 Docker是什么&#xff1a;定义和核心概念解释 Docker是一个开源项目&#xff0c;它诞生于2013年&#xff0c;旨在自动化应用程序的部署过程&#xff0c; 让应用程序能够在轻量级的、可移植的、自给自足的容器中运行。这些容器可以在几乎任何机器上运行&#xf…