【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仍然指向那块空间,那块空间在调用其他函数时可能会被调用,所以产生随机值。
综上所述,当函数返回时,如果返回对象还未还给系统,则可以使用引用返回,如果已经还给系统了,则必须使用传值返回。当然第一引用返回肯定是对的。以后的则不一定。
八、传值和引用效率比较
值传递:在传参和返回期间,函数不会直接传递实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值类型,效率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低。
引用传递:传递的是别名
九、引用与指针区别
- 相同点:
本质:引用在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。 在底层实现上实际是有空间的,因为引用是按照指针方式来实现的。因此引用的底层实现上是按照指针的方式来实现的。 - 不同点:
- 引用在定义时必须初始化,指针没有要求
- 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体
- 没有NULL引用,但有NULL指针
- 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)
- 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
- 有多级指针,但是没有多级引用
- 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
- 引用比指针使用起来相对更安全
相关文章:
【C++】引用’‘的深入解析
💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤 📃个人主页 :阿然成长日记 …...
java链式编程对象序列化问题
在使用 openfeign 进行服务之间数据传输时发现了一个问题,数据在下游正常处理,响应到调用端数据也读取到了,但是就是 jackson 转对象序列化时出了问题,异常如下 Failed to complete request: feign.codec.DecodeException: Type d…...
关于Redis(Redisson)超时问题的分析
概述 生产环境中流量高峰期会出现短时间的redis异常,主要报错如下: Redis server response timeoutRedisTimeoutException: Command execution timeout for command: (PING)Command still hasn’t been written into connection! 根据redisson官方所述…...
Redis 主从复制,哨兵,集群——(2)哨兵篇
目录 1. Redis 哨兵是什么? 2. Redis 哨兵有什么用? 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的解决方法
使用国内镜像源,但install仍旧一直卡在solving environment,超过10分钟就不用等了; 检查C:\Users\UserName 路径下的.condarc文件 将这个defaults这一行删掉即可...
神经网络和AI的关系
神经网络(Neural Networks)和人工智能(Artificial Intelligence,AI)之间存在紧密的关系,可以概括为以下几点: 神经网络是AI的子领域:神经网络是人工智能的一个子领域,它是…...
[牛客]计算机网络习题笔记_1020
1、物理层:以太网 调制解调器 电力线通信(PLC) SONET/SDH G.709 光导纤维 同轴电缆 双绞线等。 2、数据链路层(网络接口层包括物理层和数据链路层):Wi-Fi(IEEE 802.11) WiMAX(IEEE 802.16) ATM DTM 令牌环 以太网 FDD…...
蓝牙音视频远程控制协议(AVRCP)介绍
零.声明 本专栏文章我们会以连载的方式持续更新,本专栏计划更新内容如下: 第一篇:蓝牙综合介绍 ,主要介绍蓝牙的一些概念,产生背景,发展轨迹,市面蓝牙介绍,以及蓝牙开发板介绍。 第二篇:Trans…...
家庭WIFI路由器、无线网卡购买指南
一、参考资料 【Wi-Fi】802.11/802.11b/802.11g/802.11n/802.11a/802.11ac/802.11ax/802.11be 从带宽到路由,从有线到无线,从需求到选购,从布网到实测,全部说尽。基础篇(1) 【一文详解】802.11a/b/g/n/ac/…...
Matlab2022b软件如何切换中/英文界面?
在中文Windows操作系统中,MATLAB2015b之后版本安装默认为中文版,但有部分用户还是习惯使用英文界面下的MATLAB(个人偏好),下面以R2022b版分享一下中/英文界面的切换方法,超简单。 一、中文切换为英文界面&…...
通过后端数据交互,实现【会议Oa小程序】首页数据渲染
🏅我是默,一个在CSDN分享笔记的博主。📚📚 🌟在这里,我要推荐给大家我的专栏《微信小程序 》。🎯🎯 🚀无论你是编程小白,还是有一定基础的程序员,…...
I.MX6U开发板上的Qt串口编程
真正串口通讯所需的功能是比较多的,此处的上位机只实现发送和接收功能。因为Linux、windows和开发板上均有串口,所以所开发的上位机在其上都是可以运行的。 文章目录 1. 资源简介2. 应用实例2.1 项目简介:2.2 03_serialport.pro2.3 mainwind…...
深入理解多线程编程和 JVM 内存模型
文章目录 1. 理解进程和线程的概念进程(Process)线程(Thread) 2. 理解竞态条件和死锁竞态条件(Race Condition)死锁(Deadlock) 3. JVM 内存模型堆(Heap)栈&am…...
QML(25)——文本输入框组件的区别(TextField TextInput TextArea TextEdit)
目录 效果展示适用场景文本组件TextLabelText和Label的区别 单行文本输入框TextFieldTextInputTextField 和 TextInput的区别 多行文本输入框TextAreaTextArea 和 TextEdit 的区别 效果展示 适用场景 场景组件属性短文本Text长文本 末尾省略Textelide: Text.ElideRight文本设置…...
SpringBoot连接MySQL密码错误,报错:Access denied for user
记:一次连接MySQL报密码错误,Access denied for user 检查步骤: 核对用户和密码是否正确,用工具登陆试下。如果配置文件是yml格式,配置密码是123456这种纯数字,记得加上单/双引号。检查云上数据库配置&am…...
如何使用visual studio 2010构建SQLite3.lib文件
sqlite3官网只提供了dll,并没有lib文件。需要自己生成sqlite3.lib。因项目升级到x64,以前并没有生成64位的链接库,需要自己创建。本人电脑操作系统windows 10, 开发环境为visual studio 2010。下面是详细生成过程。 1. 从源下载源(…...
反转链表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...
数字图像处理实验记录五(图像的空间域增强-锐化处理)
前言: 文章目录 一、基础知识1,什么是锐化?2,为什么要锐化?3,怎么进行锐化? 二、实验要求任务1:任务2:任务3: 三、实验记录:任务1:任…...
未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...
