【C++】C++入门基础:引用详解

本篇继续分享关于C++入门的相关知识,有关命名空间、缺省参数和函数重载的部分欢迎阅读我的上一篇文章【C++】C++入门基础详解(1)_王笃笃的博客-CSDN博客

继续我们的学习

引用

在C语言中我们接触过指针,很多人都或多或少为他感到头痛过,很多C语言的使用者包括创始人都觉得很难用,所以便创造出了引用。

1.引用的概念

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

举个例子,就比如你叫李四,同学给你起了外号叫小四,你妈妈给你取的小名叫四四,这些名字都指的是李四,这么说应该不难理解;

上代码感受一下

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

可以看到我们创建出了一个整形a,使用&符号创建了b,这里的b就是a的别名,他们公用一段内存空间。

很明显&符号在类型和定义的变量中间会被当作引用符号,否则就是取地址,我们也可以看出a和b共用同一块空间;

当我们给a和b同时++运算时

 可以看到他们都参与了运算,因为他们本质上就是对同一个数据进行操作;

可以简单的使用在两数交换之中

 可以看到传值并不会真正的实现转换,但是我们用引用的方法传参

 

 可以看到两数交换成功了。

在这里里我们在函数中用引用定义参数意义是给实参取了别名,x的别名就是a,y的别名就是b,我们对a和b进行操作实际上就是对x和y进行操作。

还有一种用C语言实现链表的场景

typedef struct ListNode
{int val;struct ListNode* next;
}ListNode;void Push_back(ListNode** pphead, int x)
{ListNode* newnode = (ListNode*)malloc(sizeof(ListNode) * sizeof(int));if (*pphead == NULL){*pphead = newnode;}else{}
}
int main()
{ListNode* plist = NULL;Push_back(&plist, 1);Push_back(&plist, 2);Push_back(&plist, 3);
}

这里的重点是二级指针的使用,当时我在写二级指针的时候也是非常头疼,但是我我们现在学习了引用可以对上面的代码进行优化;

typedef struct ListNode
{int val;struct ListNode* next;
}ListNode;void Push_back(ListNode*& phead, int x)
{ListNode* newnode = (ListNode*)malloc(sizeof(ListNode) * sizeof(int));if (phead == NULL){phead = newnode;}else{}
}
int main()
{ListNode* plist = NULL;Push_back(plist, 1);Push_back(plist, 2);Push_back(plist, 3);
}

可以看到现在的phead就是plist的别名,也就是说操作phead就可以达到操作plist的目的,这样就不用再纠结二级指针的使用,同样可以达到二级指针的效果。

通过以上代码我们可以知道引用作为形参,其他函数传参时引用可以影响实参。

接下来是引用使用时需要注意的一些小细节;

2.引用的特性

使用引用的时候必须初始化

 不能说只取外号没有真正的名字,这样的用法是错误的;

同时一个变量可以被多次引用,也就是说一个人可以有很多个外号,也可以给外号取外号;

int main()
{int a = 0;int& b = a;int& c = a;int& d = a;int& e = d;return 0;
}

这些都是可行的,虽然有很多引用但是它的底层都是对a进行操作;

还需要注意的是引用一但引用了一个实体,就不能再引用其他实体,也就是说上面的b、c、d、e不能再当作别人的外号。

 

可以看到报错说e被多次初始化,这也是C++的引用和java的引用区别,C++的引用只能引用一个实体,java的引用是可以改变指向的,这样就导致C++不能脱离指针,Java可以脱离指针。

3.引用做返回值

在刚开始认识函数时我们接触过传值返回

需要注意的是这里返回值并不是n,而是n的值 

 同时也有一种用法,但是这种用法非常危险。

那就是函数传引用返回

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

为什么会这种用法会非常危险呢?

我们知道调用函数时会建立栈帧,函数内部的临时变量都会在调用函数结束时失效,在这里传引用返回就相当于给没有名字的空间起了别名,类似于野指针的后果,所以这种情况输出可能会有两种情况,一种是正常输出,一种会输出随机值

 

可以看到在vs的平台下会输出1,但是下方的结果或有一个waring

 

 我们再用一段代码来解释传引用返回的影响;

int& Add(int x, int y)
{int c = x + y;return c;
}int main()
{int& ret = Add(1,2);Add(2, 3);cout << "Add(1,2) is" << ret << endl;return 0;
}

以下是运行结果

 这里的原因是先用1和2调用了Add函数,并且将此次调用函数所占用的空间取了别名叫做ret,此时Add函数除了作用域后里面的数值都会被销毁,而空间还会被留下来,此时再次用2和3去调用Add,那么此次调用就会使用Add的栈帧空间,就得到了如上结果。

形象的说就是你在某一家酒店开了房,走的时候发现有东西没拿上,所以重新回房间里拿了东西,希望大家可以理解。

所以分享了以上错误的使用方式可以得到一个结论:如果函数返回时,出了函数作用域,如果返回对象没有返还给系统,则可以使用引用返回;如果已经返还给系统,则必须使用传值返回。

传引用返回在有些场景下也有着便捷的作用;

当初在学习数据结构时使用C语言完成链表是非常繁琐的

这里简单使用链表找到第i个位置的数据和修改数据

struct SeqList
{int* a;int size;int capacity;
};
//找到第i个位置
int SLAt(SeqList* ps, int i)
{assert(i < ps->size);return ps->a[i];
}
//修改
int SLModify(SeqList* ps, int i,int x)
{assert(i < ps->size);ps->a[i]=x;}

可以感觉到C语言的接口非常的繁琐;

下面是C++读或修改数据的接口

 

int& SLAt(SeqList* ps, int i)
{assert(i < ps->size);return ps->a[i];
}

可以看到非常非常简单,只需要在返回类型前加上引用符号即可完成读取和修改的操作,

当然也可也全部使用引用减少拷贝的时间消耗

int& SLAt(SeqList& ps, int i)
{assert(i < ps.size);return ps.a[i];
}

通过main函数来简单使用

 这样我们既可以完成读取

也可以完成修改操作

所以引用做返回值也有它合适的场景。

以上就是本片要分享的关于C++引用的使用,如果对你有所帮助还请三连支持,感谢您的阅读。

 

 

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

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

相关文章

使用SSH隧道将Ubuntu云服务器Jupyter Notebook端口映射到本地

本文主要实现了在Ubuntu云服务器后台运行Jupyter Notebook&#xff0c;并使用SSH隧道将服务器端口映射到本地 1. 生成配置文件 运行以下命令生成Jupyter Notebook的配置文件&#xff1a; jupyter notebook --generate-config这将在用户主目录下生成一个名为.jupyter的文件夹&…

【傅里叶级数与傅里叶变换】数学推导——3、[Part4:傅里叶级数的复数形式] + [Part5:从傅里叶级数推导傅里叶变换] + 总结

文章内容来自DR_CAN关于傅里叶变换的视频&#xff0c;本篇文章提供了一些基础知识点&#xff0c;比如三角函数常用的导数、三角函数换算公式等。 文章全部链接&#xff1a; 基础知识点 Part1&#xff1a;三角函数系的正交性 Part2&#xff1a;T2π的周期函数的傅里叶级数展开 P…

【Rust日报】2023-08-18 RustShip:一个新的 Rust 播客

探索 Rust 编译器基准测试套件 在最近关于 Rust 编译器 CI&#xff08;持续集成&#xff09;和基准测试基础设施的文章中&#xff0c;作者承诺写一篇关于运行时基准测试的博客文章&#xff0c;这是 Rust 编译器基准测试套件的新补充。然而&#xff0c;在这样做之前&#xff0c;…

回归预测 | MATLAB实现SSA-SVM麻雀搜索算法优化支持向量机多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现SSA-SVM麻雀搜索算法优化支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现SSA-SVM麻雀搜索算法优化支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09;效果一览基…

aardio窗体缩放自动匹配批量生成plus实例

import win.ui; /*DSG{{*/ var winform win.form(text"窗体缩放批量生成plus";right759;bottom469;bgcolor15780518) winform.add( custom{cls"custom";text"自定义控件";left3;top6;right753;bottom460;ah1;aw1;bgcolor15780518;z1} ) /*}}*//…

UML基础模型

目录 1.抽象类2.接口3.继承4.实现接口5.关联关系6.聚合关系7.合成&#xff08;组合&#xff09;关系8.依赖关系 1.抽象类 矩形框代表一个类&#xff08;Class&#xff09;。 类图分为三层&#xff1a; 第一层显示类的名称&#xff0c;如果是抽象类&#xff0c;就用斜体显示&am…

操作系统的体系结构、内核、虚拟机

&#x1f40c;个人主页&#xff1a; &#x1f40c; 叶落闲庭 &#x1f4a8;我的专栏&#xff1a;&#x1f4a8; c语言 数据结构 javaweb 石可破也&#xff0c;而不可夺坚&#xff1b;丹可磨也&#xff0c;而不可夺赤。 操作系统结构 一、操作系统体系结构1.1操作系统的内核1.1.…

TiDB 多集群告警监控-中章-融合多集群 Grafana

作者&#xff1a; longzhuquan 原文来源&#xff1a; https://tidb.net/blog/ac730b0f 背景 随着公司XC改造步伐的前进&#xff0c;越来越多的业务选择 TiDB&#xff0c;由于各个业务之间需要物理隔离&#xff0c;避免不了的 TiDB 集群数量越来越多。虽然每套 TiDB 集群均有…

Gateway网关路由以及predicates用法(项目中使用场景)

1.Gatewaynacos整合微服务 服务注册在nacos上&#xff0c;通过Gateway路由网关配置统一路由访问 这里主要通过yml方式说明&#xff1a; route: config: #type:database nacos yml data-type: yml group: DEFAULT_GROUP data-id: jeecg-gateway-router 配置路由&#xff1a;…

宁德时代与陕汽签署十年战略合作协议,助力商用车电动化进程

据报道&#xff0c;宁德时代新能源科技股份有限公司与陕西汽车控股集团有限公司已经签署了一项为期十年的战略合作协议。双方的合作旨在推动商用车电池技术的发展&#xff0c;并面向商用车全领域应用。 这次战略合作具有重要意义&#xff0c;为宁德时代和陕汽启动了全面合作的序…

2021年3月全国计算机等级考试真题(C语言二级)

2021年3月全国计算机等级考试真题&#xff08;C语言二级&#xff09; 第1题 算法空间复杂度的度量方法是&#xff08;&#xff09; A. 算法程序的长度 B. 算法所处理的数据量 C. 执行算法所需要的工作单元 D. 执行算法所需要的存储空间 正确答案&#xff1a;D 第2题 下列叙…

【自创】关于前端js的“嵌套地狱”的遍历算法

欢迎大家关注我的CSDN账号 欢迎大家关注我的哔哩哔哩账号&#xff1a;卢淼儿的个人空间-卢淼儿个人主页-哔哩哔哩视频 此saas系统我会在9月2号之前&#xff0c;在csdn及哔哩哔哩上发布成套系列教学视频。敬请期待&#xff01;&#xff01;&#xff01; 首先看图 这是我们要解…

Spring Boot 知识集锦之Spring-Batch批处理组件详解

文章目录 0.前言1.参考文档2.基础介绍2.1. 核心组件 3.步骤3.1. 引入依赖3.2. 配置文件3.3. 核心源码 4.示例项目5.总结 0.前言 背景&#xff1a; 一直零散的使用着Spring Boot 的各种组件和特性&#xff0c;从未系统性的学习和总结&#xff0c;本次借着这个机会搞一波。共同学…

无涯教程-TensorFlow - TensorBoard可视化

TensorFlow包含一个可视化工具&#xff0c;称为TensorBoard&#xff0c;它用于分析数据流图&#xff0c;还用于了解机器学习模型。 TensorBoard的重要功能包括查看有关垂直对齐的任何图形的参数和详细信息的不同类型统计的视图。 深度神经网络包括多达36&#xff0c;000个节点…

HCIP——VLAN实验2

一.实验要求 1.PC1/3的接口均为access模式&#xff0c;且属于van2&#xff0c;在同一网段 2.PC2/4/5/6的IP地址在同一网段&#xff0c;与PC1/3不在同一网段 3.PC2可以访问4/5/6&#xff0c;PC4不能访问5/6&#xff0c;PC5不能访问PC6 4.所有PC通过DHCP获取ip地址&#xff0c;PC…

《合成孔径雷达成像算法与实现》Figure3.10

代码复现如下&#xff1a; clc clear close all% 参数设置 TBP 100; % 时间带宽积 T 7.2e-6; % 脉冲持续时间 t_0 1e-6; % 脉冲回波时延% 参数计算 B TBP/T; …

unity 之Transform组件(汇总)

文章目录 理论指导结合例子 理论指导 当在Unity中处理3D场景中的游戏对象时&#xff0c;Transform 组件是至关重要的组件之一。它管理了游戏对象的位置、旋转和缩放&#xff0c;并提供了许多方法来操纵和操作这些属性。以下是关于Transform 组件的详细介绍&#xff1a; 位置&a…

C++进阶 特殊类的设计

本篇博客介绍&#xff1a;介绍几种特殊的类 特殊类的设计 设计一个类不能被拷贝设计一个类 只能在堆上创建对象设计一个类 只能在栈上创造对象设计一个类不能被继承单例模式饿汉模式懒汉模式单例模式对象的释放问题 总结 设计一个类不能被拷贝 我们的拷贝只会发生在两个场景当…

利用POM完成脚本分离实现企业级自动化(POM设计模式+页面的框架封装+测试报告截图)

利用POM完成脚本分离实现企业级自动化&#xff08;POM设计模式页面的框架封装测试报告截图&#xff09; 项目-测试-手工测试 项目-测试-手工测试 1.了解需求&#xff1b; 2.编写测试用例&#xff08;开始&#xff09;——功能测试组会去做的事情 3.执行测试用例——发送测试报…

Mac 开发 Tang Nano FPGA 指南(使用终端和使用 VS Code 和插件,适用所有 Gowin FPGA)

最近收到了一个 Tang nano 9K FPGA开发板&#xff0c;就想借此机会研究一下。 官方文档里介绍如果想使用高云的 FPGA&#xff0c;就需要使用 GOWIN IDE&#xff0c;但是需要申请 license 提交一堆资料&#xff0c;我是别人送的就不太方便让别人弄。加上 IDE 其实并不是很适合学…