当前位置: 首页 > news >正文

【C++】引用’‘的深入解析

在这里插入图片描述

💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤
📃个人主页 :阿然成长日记 👈点击可跳转
📆 个人专栏: 🔹数据结构与算法🔹C语言进阶
🚩 不能则学,不知则问,耻于问人,决无长进
🍭 🍯 🍎 🍏 🍊 🍋 🍒 🍇 🍉 🍓 🍑 🍈 🍌 🍐 🍍

文章目录

  • 一、什么是引用
  • 二、引用的表示及运算符重载
    • 1.运算符重载
    • 2.引用的表示方法
  • 三、引用的本质
    • 1.问题引入
    • 2.结论
  • 四、引用的三大特性
    • 1.引用在定义时必须初始化
    • 2.一个变量可以有多个引用
    • 3.引用一旦引用一个实体,再不能引用其他实体
  • 五、常引用
  • 六、使用场景
    • 1.做参数
    • 2.做返回值
      • (1)传值:
      • (2)引用做返回值
  • 七 、引用导致野指针
    • 对比1:
    • 对比2:
  • 八、传值和引用效率比较
  • 九、引用与指针区别

一、什么是引用

🔸 那在我们日常的生活中每个人都或多或少存在一个"外号",例如《西游记》中孙悟空就有诸多外号:美猴王,孙行者,齐天大圣等等。
🔸 那么在C++中,给一个已经存在的变量取别名,这就是引用。

二、引用的表示及运算符重载

1.运算符重载

重载是C++新增的机制,将语义和功能相似的函数用同一个名字表示,提高函数的通用性。通过重载,同一个运算符将会有不同的含义。编译器会通过上下文来确定运算符的含义。
除了这里所提到的,其实在C++中还有一些运算符重载的情况。

C语言C++
&取地址&引用

例如:* 即表示乘法,又表示对指针的解引用操作;<<即表示插入运算符,又表示按位左移运算符等。

2.引用的表示方法

类型 & 引用变量名或者对象名 = 引用实体;

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

三、引用的本质

1.问题引入

#include <iostream>
using namespace std;
int main()
{//引用:取别名int a = 10;int& b = a;//定义引用类型int& c = b;return 0;
}

执行上述代码,进行调试观察他们的内存,发现a,b,c所指向的是同一块内存空间。
在这里插入图片描述

2.结论

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

四、引用的三大特性

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

1.引用在定义时必须初始化

由于引用是对已经存在的变量进行取别名,因此使用引用时必须指定变量。

int main()
{int a = 10;int& b ;//定义引用类型return 0;
}

如上,没有为b指定变量,系统报错!
在这里插入图片描述

2.一个变量可以有多个引用

在C++语法中,一个变量有多个引用,就类似于一个人可以有多个外号。
例如:

int main()
{//引用:取别名int a = 10;int& b = a;//定义引用类型int& c = b;return 0;
}

a的引用有b,c两个。

3.引用一旦引用一个实体,再不能引用其他实体

这个也比较好理解,因为引用一旦引用了一个已经存在的实体,就是这个实体的别名,当然不能再成为其他实体的别名。

int main()
{//引用:取别名int a = 10;int m = 99;int& b = a;int& b = m;return 0;
}

上述代码,我们给b引用了变量a,又引用了变量m。
在这里插入图片描述

五、常引用

引用原则:对原变量的引用,权限不能放大。但可以缩小。

例如:

int main()
{const int a = 10;int& b = a;return 0;
}

在这里插入图片描述

这段代码中x变量是const修饰是一个常变量,只有可读权限。而我们引用的类型是int,不仅有可读权限,还有可修改权限。这就造成了对原变量的权限放大。

六、使用场景

1.做参数

Swap函数中,x是a的别名,y是b的别名。

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

以引用作为函数参数,效率更高。

2.做返回值

(1)传值:

int Count()
{static int n = 0;n++;return n;
}
int main()
{cout << Count() << endl;return 0;
}

底层逻辑:
在这里插入图片描述
因为在当临时变量出了函数作用域之后会销毁,函数栈桢也会销毁,那么此时n是不能作为返回值再赋值给ret的。那么编译器就在此生成了一个临时变量,把n拷给临时变量,再把临时变量给ret。此时,函数栈桢销毁是不会影响临时变量的。所以,传值是会拷贝一份临时变量。

(2)引用做返回值

int& Count()
{int n = 0;n++;cout <<"n的地址"<< & n << endl;return n;
}
int main()
{int& ret = Count();cout << "ret的地址" << &ret << endl;return 0;
}

在这里插入图片描述

这里可以这么认为,中间也会产生一个临时变量,这个临时变量tmp的类型为int&,此时这个临时变量是n的别名,再把临时变量赋给ret。返回的是一个n的别名,就相当于是把n返回给了ret。这里ret和n的地址相同,也能证明ret是n的别名。因此,引用作为返回值其实返回的就是n的别名。
还需要注意,函数调用完会销毁栈,但是此时的ret仍然指向的原来栈帧。这也引出了下面的问题

七 、引用导致野指针

对比1:

使用变量ret接收返回值:int ret = Count();

int& Count()
{int n = 0;n++;cout <<"n的地址"<< & n << endl;return n;
}
int main()
{int ret = Count();cout << "ret1->" << ret << endl;cout << "ret2->" << ret << endl;cout << "ret3->" << ret << endl;return 0;
}

在这里插入图片描述
返回三次,结果相同!
这是因为,ret是一个变量,在main函数中,它已经接收到了Count函数的返回值一个int型的变量并保存起来。只要我们不去改动ret的值,不会变。

对比2:

使用引用接收返回值: int& ret = Count();

int& Count()
{int n = 0;n++;cout <<"n的地址"<< & n << endl;return n;
}
int main()
{int& ret = Count();cout << "ret1" << ret << endl;cout << "ret2" << ret << endl;cout << "ret3" << ret << endl;return 0;
}

在这里插入图片描述
ret的三次打印值不同!

这是因为1.函数栈帧调用完会销毁,2.我们使用的是引用操作ret来接收返回值。这个ret在这里其实就是n的别名,接收到的是一块空间,Count函数调用结束后,已经被销毁,但是ret仍然指向那块空间,那块空间在调用其他函数时可能会被调用,所以产生随机值。

综上所述,当函数返回时,如果返回对象还未还给系统,则可以使用引用返回,如果已经还给系统了,则必须使用传值返回。当然第一引用返回肯定是对的。以后的则不一定。

八、传值和引用效率比较

值传递:在传参和返回期间,函数不会直接传递实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值类型,效率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低。
引用传递:传递的是别名

九、引用与指针区别

  • 相同点:
    本质:引用在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。 在底层实现上实际是有空间的,因为引用是按照指针方式来实现的。因此引用的底层实现上是按照指针的方式来实现的。
  • 不同点:
  1. 引用在定义时必须初始化,指针没有要求
  2. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体
  3. 没有NULL引用,但有NULL指针
  4. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)
  5. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
  6. 有多级指针,但是没有多级引用
  7. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
  8. 引用比指针使用起来相对更安全

相关文章:

【C++】引用’‘的深入解析

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …...

java链式编程对象序列化问题

在使用 openfeign 进行服务之间数据传输时发现了一个问题&#xff0c;数据在下游正常处理&#xff0c;响应到调用端数据也读取到了&#xff0c;但是就是 jackson 转对象序列化时出了问题&#xff0c;异常如下 Failed to complete request: feign.codec.DecodeException: Type d…...

关于Redis(Redisson)超时问题的分析

概述 生产环境中流量高峰期会出现短时间的redis异常&#xff0c;主要报错如下&#xff1a; Redis server response timeoutRedisTimeoutException: Command execution timeout for command: (PING)Command still hasn’t been written into connection! 根据redisson官方所述…...

Redis 主从复制,哨兵,集群——(2)哨兵篇

目录 1. Redis 哨兵是什么&#xff1f; 2. Redis 哨兵有什么用&#xff1f; 2.1 主动监控 2.2 消息通知 2.3 故障转移 2.4 配置中心 3. Redis 哨兵数量配备要求 4. 哨兵配置文件详解 5. quorum 投票数详解 5.1 quorum 的含义 5.2 网络抖动导致主观下线 5.3 quorum …...

C++入门笔记分享

有道云笔记...

使用conda install一直卡在solving environment的解决方法

使用国内镜像源&#xff0c;但install仍旧一直卡在solving environment&#xff0c;超过10分钟就不用等了&#xff1b; 检查C:\Users\UserName 路径下的.condarc文件 将这个defaults这一行删掉即可...

神经网络和AI的关系

神经网络&#xff08;Neural Networks&#xff09;和人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;之间存在紧密的关系&#xff0c;可以概括为以下几点&#xff1a; 神经网络是AI的子领域&#xff1a;神经网络是人工智能的一个子领域&#xff0c;它是…...

[牛客]计算机网络习题笔记_1020

1、物理层&#xff1a;以太网 调制解调器 电力线通信(PLC) SONET/SDH G.709 光导纤维 同轴电缆 双绞线等。 2、数据链路层&#xff08;网络接口层包括物理层和数据链路层&#xff09;&#xff1a;Wi-Fi(IEEE 802.11) WiMAX(IEEE 802.16) ATM DTM 令牌环 以太网 FDD…...

蓝牙音视频远程控制协议(AVRCP)介绍

零.声明 本专栏文章我们会以连载的方式持续更新&#xff0c;本专栏计划更新内容如下&#xff1a; 第一篇:蓝牙综合介绍 &#xff0c;主要介绍蓝牙的一些概念&#xff0c;产生背景&#xff0c;发展轨迹&#xff0c;市面蓝牙介绍&#xff0c;以及蓝牙开发板介绍。 第二篇:Trans…...

家庭WIFI路由器、无线网卡购买指南

一、参考资料 【Wi-Fi】802.11/802.11b/802.11g/802.11n/802.11a/802.11ac/802.11ax/802.11be 从带宽到路由&#xff0c;从有线到无线&#xff0c;从需求到选购&#xff0c;从布网到实测&#xff0c;全部说尽。基础篇&#xff08;1&#xff09; 【一文详解】802.11a/b/g/n/ac/…...

Matlab2022b软件如何切换中/英文界面?

在中文Windows操作系统中&#xff0c;MATLAB2015b之后版本安装默认为中文版&#xff0c;但有部分用户还是习惯使用英文界面下的MATLAB&#xff08;个人偏好&#xff09;&#xff0c;下面以R2022b版分享一下中/英文界面的切换方法&#xff0c;超简单。 一、中文切换为英文界面&…...

通过后端数据交互,实现【会议Oa小程序】首页数据渲染

&#x1f3c5;我是默&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;在这里&#xff0c;我要推荐给大家我的专栏《微信小程序 》。&#x1f3af;&#x1f3af; &#x1f680;无论你是编程小白&#xff0c;还是有一定基础的程序员&#xff0c;…...

I.MX6U开发板上的Qt串口编程

真正串口通讯所需的功能是比较多的&#xff0c;此处的上位机只实现发送和接收功能。因为Linux、windows和开发板上均有串口&#xff0c;所以所开发的上位机在其上都是可以运行的。 文章目录 1. 资源简介2. 应用实例2.1 项目简介&#xff1a;2.2 03_serialport.pro2.3 mainwind…...

深入理解多线程编程和 JVM 内存模型

文章目录 1. 理解进程和线程的概念进程&#xff08;Process&#xff09;线程&#xff08;Thread&#xff09; 2. 理解竞态条件和死锁竞态条件&#xff08;Race Condition&#xff09;死锁&#xff08;Deadlock&#xff09; 3. JVM 内存模型堆&#xff08;Heap&#xff09;栈&am…...

QML(25)——文本输入框组件的区别(TextField TextInput TextArea TextEdit)

目录 效果展示适用场景文本组件TextLabelText和Label的区别 单行文本输入框TextFieldTextInputTextField 和 TextInput的区别 多行文本输入框TextAreaTextArea 和 TextEdit 的区别 效果展示 适用场景 场景组件属性短文本Text长文本 末尾省略Textelide: Text.ElideRight文本设置…...

SpringBoot连接MySQL密码错误,报错:Access denied for user

记&#xff1a;一次连接MySQL报密码错误&#xff0c;Access denied for user 检查步骤&#xff1a; 核对用户和密码是否正确&#xff0c;用工具登陆试下。如果配置文件是yml格式&#xff0c;配置密码是123456这种纯数字&#xff0c;记得加上单/双引号。检查云上数据库配置&am…...

如何使用visual studio 2010构建SQLite3.lib文件

sqlite3官网只提供了dll&#xff0c;并没有lib文件。需要自己生成sqlite3.lib。因项目升级到x64&#xff0c;以前并没有生成64位的链接库&#xff0c;需要自己创建。本人电脑操作系统windows 10, 开发环境为visual studio 2010。下面是详细生成过程。 1. 从源下载源&#xff08…...

反转链表review

反转链表 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val val; }* ListNode(int val, ListNode next) { this.val val; this.next next; }* }*/ class …...

UG\NX二次开发 获取用户默认设置中的绘图信息 UF_PLOT_ask_session_job_options

文章作者:里海 来源网站:《里海NX二次开发3000例专栏》 感谢粉丝订阅 感谢 m0_58724732 订阅本专栏,非常感谢。 简介 UG\NX二次开发 获取用户默认设置中的绘图信息 UF_PLOT_ask_session_job_options 效果 代码 #include "me.hp...

数字图像处理实验记录五(图像的空间域增强-锐化处理)

前言&#xff1a; 文章目录 一、基础知识1&#xff0c;什么是锐化&#xff1f;2&#xff0c;为什么要锐化&#xff1f;3&#xff0c;怎么进行锐化&#xff1f; 二、实验要求任务1&#xff1a;任务2&#xff1a;任务3&#xff1a; 三、实验记录&#xff1a;任务1&#xff1a;任…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录

ASP.NET Core 是一个跨平台的开源框架&#xff0c;用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录&#xff0c;以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

微信小程序 - 手机震动

一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注&#xff1a;文档 https://developers.weixin.qq…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比

在机器学习的回归分析中&#xff0c;损失函数的选择对模型性能具有决定性影响。均方误差&#xff08;MSE&#xff09;作为经典的损失函数&#xff0c;在处理干净数据时表现优异&#xff0c;但在面对包含异常值的噪声数据时&#xff0c;其对大误差的二次惩罚机制往往导致模型参数…...

vulnyx Blogger writeup

信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面&#xff0c;gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress&#xff0c;说明目标所使用的cms是wordpress&#xff0c;访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...

iview框架主题色的应用

1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题&#xff0c;无需引入&#xff0c;直接可…...

GO协程(Goroutine)问题总结

在使用Go语言来编写代码时&#xff0c;遇到的一些问题总结一下 [参考文档]&#xff1a;https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现&#xff1a; 今天在看到这个教程的时候&#xff0c;在自己的电…...

如何应对敏捷转型中的团队阻力

应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中&#xff0c;明确沟通敏捷转型目的尤为关键&#xff0c;团队成员只有清晰理解转型背后的原因和利益&#xff0c;才能降低对变化的…...

02.运算符

目录 什么是运算符 算术运算符 1.基本四则运算符 2.增量运算符 3.自增/自减运算符 关系运算符 逻辑运算符 &&&#xff1a;逻辑与 ||&#xff1a;逻辑或 &#xff01;&#xff1a;逻辑非 短路求值 位运算符 按位与&&#xff1a; 按位或 | 按位取反~ …...

门静脉高压——表现

一、门静脉高压表现 00:01 1. 门静脉构成 00:13 组成结构&#xff1a;由肠系膜上静脉和脾静脉汇合构成&#xff0c;是肝脏血液供应的主要来源。淤血后果&#xff1a;门静脉淤血会同时导致脾静脉和肠系膜上静脉淤血&#xff0c;引发后续系列症状。 2. 脾大和脾功能亢进 00:46 …...