一篇文章带你搞懂C++引用(建议收藏)
引用
6.1 引用概念
引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。
比如:李逵,在家称为"铁牛",江湖上人称"黑旋风"
typedef 是给类型取别名
引用是给变量取别名
注意:引用类型必须和引用实体是同种类型的
类型& 引用变量名(对象名) = 引用实体;
int main()
{int a = 0;//定义一个变量a,赋值为0,int &b = a;//这里的&不是取地址符,而是引用,给变量取别名, &定义在一个类型和变量之间为引用//定义一个空间为a,又给这个空间a取别名为bint a = 0;int b = a;//这种写法和上面是完全不同的,//这里是 定义一个变量为a,a的值是0,定义一个变量为b,用a的0初始化return 0;
}
如何证明是否公用一块空间?
#include <iostream>
using namespace std;int main()
{int a = 0;int& b = a;cout << &b << endl;//取地址cout << &a << endl;//取地址a++;b++;return 0;
}

6.2 引用的特性
1. 引用在定义时必须初始化
int main()
{int a = 1;int& b;//引用在定义时必须初始化return 0;
}
2. 一个变量可以有多个引用(可以取无限个别名)
int main()
{int a = 1;int &b = a;int &c = a;int &d = c;//还可以给别名取别名a++;return 0;
}

3. 引用一旦引用一个实体,再不能引用其他实体
指针指向一个实体后,可以改变,引用不可以改变
int main()
{int a = 1;int& b = a;int& c = a;int& d = c;int x = 10;//引用一旦拥有一个实体,再不能引用其他实体b = x;b是x的别名呢?还是x赋值为b?return 0;
}

这里把x赋值给b
6.3 常引用
权限不能放大
int main()
{int a = 13;int& b = a;//权限不能放大const int c = 20;//int& d = c;const int& d = c;//权限可以缩小,从只读的角度int e = 25;const int& f = e; return 0;
}
隐式类型转换和强制类型转换都是会产生临时变量
所有的转换都不是对原变量进行转换和提升,而是之间产生临时变量
并不会改变原变量类型,
这里本质上是权限的放大和缩小
类型转换中间是会产生临时变量的,临时变量具有常性,相当于const修饰
int main()
{int ii = 1;doubble dd = ii;//int类型可以给double,会发生隐式类型转换double& rdd = ii;//double类型的数据可以变成int的引用吗?//不可以 这里不能引用的原因不是说类型不匹配,而是不能进行权限的放大const double& rdd = ii;//这里可以引用是因为权限的平移 中间产生的临时变量也是相当于const修饰的变量//此时rdd引用的不是ii,而是int转换成double之间产生的临时变量,//这个临时变量具有常性return 0;
}


const 可以把一个常量起一个别名
const int& x = 10;
应用场景:
如果使用引用传参,函数内如果不改变n,那么尽量用const引用传参
const引用传参会有非常强的接受度
6.4 引用的使用场景
1.做参数
a.输出型参数
b.大对象传参,提高效率
2.做返回值
a.输出型返回对象,调用者可以修改返回对象.
b.减少拷贝提高效率,
不是什么时候都可以使用传引用返回,要注意使用场景
出了作用域,返回对象还在可以用传引用返回
出了作用域,返回对象销毁.那么一定不能用引用返回,一定要用传值返回
1. 做参数 --(引用的输出型参数)
如果不用引用,传入的是实参的一份临时拷贝,形参的改变不会影响实参
如果想改变 必须使用指针 传入地址
在C++里,这里x是a的别名,y是b的别名,x和y的交换就是a和b的交换
void Swap(int& x, int& y)
{int tmp = x;x = y;y = tmp;
}
int main()
{int a = 3;int b = 5;cout <<"交换前:" << a << ' ' << b << endl;Swap(a, b);cout <<"交换后:" << a << ' ' << b << endl;return 0;
}

例如:有些书里会把数据结构里链表部分弄得很复杂
typedef struct SListNode
{.....
}SLTNode,*PSLTNode;
//这里的*PSLTNode 相当于typedef struct SListNode* PSLTNode 给这个结构体指针起了个别名 PSLTNode
void SListPushBack(PSLTNode& phead,int x)//这里的引用相当于 phead是list的别名,phead的改变会影响list
{.....
}
int main()
{SLTNode* list = NULL;SListPushBack(list,1);SListPushBack(list,1);SListPushBack(list,1);return 0;
}
大对象传参 提高效率
#include <time.h>
struct A{ int a[10000]; };
void TestFunc1(A a){}
void TestFunc2(A& a){}
void TestRefAndValue()
{A a;// 以值作为函数参数size_t begin1 = clock();for (size_t i = 0; i < 10000; ++i)TestFunc1(a);size_t end1 = clock();// 以引用作为函数参数size_t begin2 = clock();for (size_t i = 0; i < 10000; ++i)TestFunc2(a);size_t end2 = clock();// 分别计算两个函数运行结束后的时间cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
}
2. 做返回值
传值返回 都会生成一个返回对象拷贝作为函数调用的返回值
返回的是n吗 是用n的拷贝来做表达式的返回值
为什么编译器要这么做?
如果这里没有static ,n返回时,出了该作用域 会销毁 置为随机值


传引用返回:
引用返回的语法含义:返回返回对象的别名
不是什么时候都可以使用传引用返回,要注意使用场景
返回n的别名 越界了为什么不报错呢?
ret的结果是未定义的 如果栈帧结束时,系统清理栈帧置成随机值,那么这里ret的结果就是随机值
下面程序使用引用返回本质是不对的,结果是没有保障的
int& Count()
{int n = 0;n++;// ...return n;
}
int main()
{int ret = Count();return 0;
}
如果引用ret ,那么相当于 ret也是n的别名,结果会不会有所不同
int& Count()
{int n = 0;n++;// ...return n;
}
int main()
{int& ret = Count();printf("%d\n", ret);printf("%d\n", ret);printf("%d\n", ret);printf("%d\n", ret);return 0;
}

总结:出了函数作用域,返回对象就销毁了,那么一定不能用引用返回,一定要用传值返回
什么时候可以用引用返回?
使用static
1. static修饰变量
a. 函数中局部变量:
声明周期延长:该变量不随函数结束而结束
初始化:只在第一次调用该函数时进行初始化
记忆性:后序调用时,该变量使用前一次函数调用完成之后保存的值
存储位置:不会存储在栈上,放在数据段
int& Count()
{static int n = 0;n++;// ...return n;
}
int main()
{int& ret = Count();printf("%d\n", ret);printf("%d\n", ret);printf("%d\n", ret);printf("%d\n", ret);return 0;
}
const引用
为什么这里给c取别名不可以?
本质上是权相的放大 c自己是const类型 不可以修改
用d取别名 使得d是权限的放大 可以修改
#include <iostream>using namespace std;int main()
{int a = 10;//权限的的平移int& b = a;const int c = 20;//权限的放大int& d = c;int e = 30;//权限的缩小const int&f = e;//只读的角度变成你的别名return 0;
}
权限不可以放大,但是权限可以缩小

int main()
{int ii = 1;double dd = ii;//发生隐式类型转换double& rdd = ii;//double不可以变成int的引用//不可以使用的本质原因是 因为权限的放大,因为 int 类型要转换成double类型//中间要先生成一个double类型的临时变量,相当于 const double ii;//double& dd = const double ii; //权限的放大不可以const double& rdd = ii;//可以使用权限的平移return 0;
}
强制转换并不是改变原变量类型 他也是产生一个临时变量

如果使用引用传参,函数内如果不改变n,那么尽量用const引用传参
void func1(int& n)
{}
void func2(const int& n)
{}
int main()
{int a = 10;const int b =20;func1(a);func1(b);func1(30);func2(a);func2(b);func2(30);double c = 1.11;func2(c);return 0;
}
指针和引用的差别
指针和引用用途基本是相似的
但有
1.使用场景的差别
引用和指针的不同点:
1. 引用在定义时必须初始化,指针没有要求
2. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型
实体
3. 没有NULL引用,但有NULL指针
4. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占
4个字节)
5. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
6. 有多级指针,但是没有多级引用
7. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
8. 引用比指针使用起来相对更安全
2.语法特性以及底层原理的差别
从语法角度而言,引用没有开辟空间,指针开了四个字节或者8个字节的空间
底层实现角度,那么引用底层是用指针实现的
个人水平不足 如果代码中有错误,可以多多在评论区指出,一定会及时修改!
谢谢大家看到这里 觉得有收获的话可以三连一下 一起加油!

相关文章:
一篇文章带你搞懂C++引用(建议收藏)
引用 6.1 引用概念 引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。 比如:李逵,在家称为"铁牛",江湖上人称&quo…...
查询SQL:文章浏览1
问题描述 请查询出所有浏览过自己文章的作者 结果按照 id 升序排列。 查询结果的格式如下所示: 题目分析: 这题主要考察排序asc(升序)、desc(降序)以及distinct字段。 解决方案: select DIS…...
android 在onCreate方法中获得view的宽高
view在绘制完成后才会有自己的宽高,所以在onCreate中要获得view的宽高可以通过以下4中方法: 1、ViewTreeObserver:监听界面绘制事件,在layout时调用,使用完毕后记得removeListener 2、view.post,因为runn…...
SOA主要协议和规范
Web服务作为实现SOA中服务的最主要手段。首先来了解Web Service相关的标准。它们大多以“WS-”作为名字的前缀,所以统称“WS-*”。Web服务最基本的协议包括UDDI、WSDL和SOAP,通过它们,可以提供直接而又简单的Web Service支持,如图…...
30、matlab现代滤波:维纳滤波/LMS算法滤波/小波变换滤波
1、信号1和信号2的维纳滤波 实现代码 N 2000; %采样点数 Fs 2000; %采样频率 t 0:1 / Fs:1 - 1 / Fs; %时间序列 Signal1 sin(2*pi*20* t) sin(2*pi*40* t) sin(2*pi*60* t); Signal2[2*ones(1,50),zeros(1,50),-1*ones(1,100),zeros(1,50),-2*ones(1,50),zeros(1,50),1…...
HTML5 视频 Vedio 标签详解
HTML5 引入了 <video> 标签,允许开发者在网页中直接嵌入视频文件,而不需要依赖第三方插件。本文将全面介绍 <video> 标签的各种属性,并通过实例代码详细说明其用法。 一、基础用法 1. 基本结构 HTML5 中使用 <video> 标…...
三十五篇:数字化转型的引擎:赋能企业的ERP系统全景
数字化转型的引擎:赋能企业的ERP系统全景 1. 引言 在这个快速变化的数字时代,现代企业面临着前所未有的挑战和机遇。企业资源计划(ERP)系统,作为数字化转型的核心,扮演着至关重要的角色。它不仅是企业运营…...
利用ArcGIS对长江三角洲地区的gdp水平进行聚类
1、导入矢量图、数据 长三角地区矢量图 长三角地区矢量图对应数据 2、连接 3、设置属性将人均gdp数据导入 4、设置标注和图例 选择布局视图 5、聚类 2020年人均gdp地区聚类 6、2005~2020年各地区人均gdp可视化及聚类汇总 (1)2005~2020可视化 2005 …...
释放视频潜力:Topaz Video AI for mac/win 一款全新的视频增强与修复利器
在数字时代,视频已经成为我们记录生活、分享经历的重要方式。然而,有时候我们所拍摄的视频可能并不完美,可能存在模糊、噪点、抖动等问题。这时候,就需要一款强大的视频增强和修复工具来帮助我们提升视频质量,让它们更…...
MongoDB 正则表达式详解:高效数据查询与处理技巧
MongoDB 的正则表达式(Regular Expression)功能允许在查询中进行模式匹配和文本搜索,为用户提供了强大的灵活性。 基本语法 MongoDB 中使用正则表达式时,通常是在查询语句中使用 $regex 操作符。基本语法如下: { &l…...
第二十六章HTML与CSS书写规范
1.HTML书写规范 1.文档类型声明及编码 统一为html5 声明类型。编码统一为utf-8。 2.页面tdk TDK是一个缩写,其中“T”表示为网页定义标题,“D”表示为网页定义描述 description,“K”表示为搜索引擎定义关键词keywords。 1、<title&g…...
基于FPGA的AD5753(DAC数模转换器)的控制 II(SPI驱动)
基于FPGA的AD5753(DAC数模转换器)的控制 II(已上板验证) 语言 :Verilg HDL EDA工具:Vivado 基于FPGA的AD5753(DAC数模转换器)的控制 II(已上板验证)一、引言二…...
【全开源】Java同城服务同城信息同城任务发布平台小程序APP公众号源码
📢 连接你我,让任务触手可及 🌟 引言 在快节奏的现代生活中,我们时常需要寻找一些便捷的方式来处理生活中的琐事。同城任务发布平台系统应运而生,它为我们提供了一个高效、便捷的平台,让我们能够轻松发布…...
[Redis]List类型
列表类型来存储多个有序的字符串,a、b、c、d、e 五个元素从左到右组成了一个有序的列表,列表中的每个字符串称为元素,一个列表最多可以存储个元素。在 Redis 中,可以对列表两端插入(push)和弹出(…...
export 和 export default 的区别
在 JavaScript 中,export 和 export default 都是用于导出模块中的内容的关键字,但它们有一些区别: export: export 关键字用于导出多个变量、函数或对象。可以一次导出多个内容,并且在导入时需要使用对应的名称。例如:…...
29网课交单平台 epay.php SQL注入漏洞复现
0x01 产品简介 29网课交单平台是一个专注于在线教育和知识付费领域的交单平台。该平台基于PHP开发,通过全开源修复和优化,为用户提供了高效、稳定、安全的在线学习和交易环境。作为知识付费系统的重要组成部分,充分利用了互联网的优势,为用户提供了便捷的支付方式、高效的…...
推荐ChatGPT4.0——Code Copilot辅助编程、Diagrams: Show Me绘制UML图、上传PDF并阅读分析
5月14日凌晨1点、太平洋时间的上午 10 点,OpenAI的GPT-4o的横空出世,再次巩固了其作为行业颠覆者的地位。GPT-4o的发布不仅仅是一个产品的揭晓,它更像是向世界宣告AI技术已迈入了一个全新的纪元,连OpenAI的领航者萨姆奥特曼也不禁…...
rollup.js(入门篇)
前沿 Rollup 是一个用于 JavaScript 的模块打包工具,它将小的代码片段编译成更大、更复杂的代码,例如库或应用程序。它使用 JavaScript 的 ES6 版本中包含的新标准化代码模块格式,而不是以前的 CommonJS 和 AMD 等特殊解决方案。ES 模块允许…...
【Spring Cloud Alibaba】开源组件Sentinel
目录 什么是Sentinel发展历史与Hystrix的异同 Sentinel可以做什么?Sentinel的功能Sentinel的开源生态Sentinel的用户安装Sentinel控制台预备环境准备Sentinel 分为两个部分:下载地址 项目集成Sentinel创建项目修改依赖信息添加启动注解添加配置信息在控制器类中新增…...
Android14 WMS-窗口绘制之relayoutWindow流程(一)-Client端
Android14 WMS-窗口添加流程(一)-Client端-CSDN博客 Android14 WMS-窗口添加流程(二)-Server端-CSDN博客 经过上述两个流程后,窗口的信息都已经传入了WMS端。 1. ViewRootImpl#setView 在窗口添加流程(一)中,有这个方法: http://aospxref…...
ClawdOS:为AI Agent构建可视化操作系统的全栈实践
1. 项目概述:为你的AI大脑装上眼睛和手如果你和我一样,是OpenClaw(前身是Moltbot/Clawdbot)的早期用户,那你一定经历过这种场景:在终端里,你的AI助手聪明绝顶,能写代码、查资料、分析…...
从MATLAB到FPGA:高效生成三种波形COE文件的实战指南
1. COE文件格式解析与FPGA应用场景 COE文件是Xilinx FPGA设计中用于初始化Block RAM(BRAM)的标准文件格式。我第一次接触这种文件时,发现它其实就是一个带有特定格式要求的文本文件,但正是这种简单的结构,让它成为MATL…...
5分钟终极指南:用Nexus Mods App告别模组管理噩梦
5分钟终极指南:用Nexus Mods App告别模组管理噩梦 【免费下载链接】NexusMods.App Home of the development of the Nexus Mods App 项目地址: https://gitcode.com/gh_mirrors/ne/NexusMods.App 还在为游戏模组冲突、依赖缺失而烦恼吗?Nexus Mod…...
量子误差缓解技术与BBGKY层次结构的应用
1. 量子误差缓解的现状与挑战在当前的NISQ(噪声中等规模量子)时代,量子计算机的实际应用面临着一个根本性障碍:量子噪声。与经典计算机不同,量子比特极易受到环境干扰,导致计算错误。这种噪声主要来源于量子…...
西门子“工业软件驱动的数字孪生”模式
西门子(Siemens)的“工业软件驱动的数字孪生”模式是全球离散制造业(如汽车、航空航天、电子)公认的技术制高点。其核心逻辑不是简单的 3D 建模,而是“数物融合”,即利用完整的软件工具链在物理实体投产前&…...
从‘方波变形记’聊起:为什么你的高速信号需要Tx EQ?一个给嵌入式软件/FPGA工程师的通俗图解
从‘方波变形记’聊起:为什么你的高速信号需要Tx EQ? 想象一下,你正在观看一场高清直播,画面突然出现马赛克;或者传输重要数据时,系统频繁报错。这些问题的根源,可能就藏在信号传输的微观世界里…...
repo2txt:Git仓库转纯文本工具,为AI分析、代码归档与审查提供完整上下文
1. 项目概述:从代码仓库到纯文本的自动化提取最近在整理个人技术笔记和项目文档时,我遇到了一个挺普遍但有点烦人的问题:如何把一个完整的Git代码仓库,包括它的目录结构、所有源代码文件以及提交历史,以一种清晰、可读…...
观察Taotoken用量看板如何帮助团队透明化管理API成本
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 观察Taotoken用量看板如何帮助团队透明化管理API成本 作为团队的技术负责人,管理大模型API成本是一项持续且细致的工作…...
NExT-GPT:从多模态对齐到任意模态生成的架构与实战
1. 项目概述:从“多模态”到“任意模态”的进化 如果你在过去一年里关注过AI领域,一定对“多模态大模型”这个词不陌生。从GPT-4V到Gemini,主流模型都在努力让AI能同时理解文本和图像。但不知道你有没有想过一个问题:为什么我们和…...
用电脑自动玩小红书,OpenClaw+ADB让效率翻倍!附详细教程“
本文介绍了如何使用OpenClaw(运行在MacOS上)结合ADB工具实现Android手机的自动化操作。内容涵盖Android手机配置(开启开发者选项和USB调试)、MacOS环境准备(安装ADB工具和配置ADBKeyboard支持中文输入)&…...
