C++ 引用 - 引用的特点|在优化程序上的作用

引用是C++ 的一个别名机制,所谓别名,就是同一块内存共用多个名字,每个名字都指的是这片空间,通过这些别名都能访问到同样的一块空间。

就像鲁迅和周树人是同一个人。

                                                                                                                            ——鲁迅

一、引用的基本用法

int a = 10;
int& ref = a; // ref 是 a 的引用ref = 20; // 这也会改变 a 的值
std::cout << a; // 输出 20

需要注意的是,这里定义的引用变量ref并不会在内存上开辟新的空间,而是给a对应的那片空间取了一个新的名字,现在通过ref也能访问到那片空间了。

`&`符号我们不会陌生,在之前他的名字是取地址符,在C++中它还有新的作用:定义引用

在使用中,主要有这两个区别和联系:

   1.定义引用时:`&`在类型之后,表示该变量是引用。

int& ref = a;

  2. 获取地址时:`&`在变量前边, 表示获取该变量的地址。

int* ptr = &a;

二、引用的特点

  • 必须初始化:引用在声明时必须进行初始化。
    int& a; //错误的!!
  • 不可重新绑定:初始化后不能再指向其他变量。
    int a = 0;
    int b = 0;int& ref = a;
    int& ref = b; //错误的!!
  • 类型一致:引用的类型必须与其引用的变量类型一致。
    int a = 0;
    float& b = a; //错误的!!
  • 权限不能放大:在引用的过程中,权限可以平移,缩小,但不能放大
    const int a = 0;
    int& b = a; //权限的放大
    const int& b = a; //权限的平移int c = 0;
    const int& d = c; //权限的缩小
  • 多个别名:一个变量可以有多个引用。
    int a = 0;
    int& ref1 = a;
    int& ref2 = a;
  • 没有独立空间:在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间(在底层实现上实际是有空间的,因为引用是按照指针方式来实现的)
    int a = 0;
    int& ref = a;
  • 没有“二级引用”、没有“空引用”
    int a = 0;
    int& ref1 = NULL; //错误的!!
    int&& ref2 = a; //错误的!!

三、引用的作用

以前的交换函数我们只能通过传递参数的指针来实现,而有了引用,我们可以通过给要交换的参数取别名的方式来实现:

#include<iostream>
using namespace std;void swap(int& a, int& b)
{int t = a;a = b;b = t;
}int main()
{int i = 6, j = 2;swap(i, j);cout << i << endl;cout << j << endl;return 0;
}

i,j是实参,a,b是形参,且由于我们在形参类型后加了`&`,也就是说定义了a,b分别是i,j的别名,现在a,b分别代表i,j的那片空间了,所以在交换函数中我们可以通过直接交换a,b的值来交换i,j的值, 从而实现了实参传给形参,形参的改变可以改变实参的功能。

再来看一个顺序表的例子,这是没有引用前我们的写法:

struct SeqList
{int a[100];int size;int capacity;
};//C实现的写法
int SLFind(struct SeqList* p, int i)
{// ... ...return p->a[i];
}void SLModify(struct SeqList* p, int i, int x)
{p->a[i] = x;
}int main()
{struct SeqList s;// ... ...SLFind(&s, 0);SLModify(&s, 0, 1);}

要实现查找和修改这两个功能,我们分别需要`SLFind`和`SLModify` 两个函数来实现,而且需要传递顺序表结构的指针才能进行对值的修改。、

而有了引用,首先我们可以优化参数的传递:改为定义引用来接收实参,从而达到修改形参实现修改实参的功能。其次我们还可以优化程序,用一个函数就能实现修改与查找的功能:

struct SeqList
{int a[100];int size;int capacity;
};//CPP实现的接口
int& SLFind(struct SeqList& p, int i)
{// ... ...return p.a[i]; // 返回引用,允许对顺序表元素进行修改
}int main()
{struct SeqList s;// ... ...SLFind(s, 0) = 1;  //Modifycout << SLFind(s, 0) << endl;  //Find
}

在上面这段代码中,我们发现引用也可以作为返回值,但其实这一作用在某些情况下是不安全的,可以看下面这个例子:

int& add(int a, int b)
{int n = a + b;return n; //返回n的别名
}int main()
{int rst = add(1, 2);cout << rst << endl;return 0;
}

这段代码的输出值是多少? 是3吗?

这段代码其实存在一个严重安全的问题:add函数返回的是局部变量 n 的引用。在 add 函数执行完毕后,局部变量 n 的生命周期结束,其内存被释放,返回的引用将指向一个已经释放的内存位置。这就像指针里我们提到的野指针。所以,具体输出的值取决于编译器,如果内存释放后编译器将这部分内存置为随机值,那么输出的值就是一个随机值。

如果改成这样呢?

int& add(int a, int b)
{int n = a + b;return n; //返回n的别名
}int main()
{int& rst = add(1, 2);cout << rst << endl;cout << rst << endl;return 0;
}

在上一段代码是将 n 的值拷贝给 rst, 输出的 rst 取决于 存放 n 的那片内存有没有被置为随机值。

而现在变成了 rst 是 n 别名,两次打印 rst 的值可能是不同的,原因:

接下来调用 cout 函数,新建立的栈帧在原来的 add 的那片空间中

由于调用前 n 的值首先被压入栈帧,所以第一次能够成功读取到 n 的值,但第二次输出的值就是不确定的了,因为 cout 可能会覆盖到存放 n  的值的那片空间(这取决于cout所需要的栈帧空间),如果覆盖到了,那么第二次调用 cout 打印 n 的值就是随机数了。

综上所述,引用的作用有:

  1. 函数参数传递:避免拷贝,提高效率。尤其是对于传递较大的结构体时,效率的提升是显著的;
  2. 实现实参传给形参,形参的改变可以改变实参;
  3. 引用作为返回值:通过返回引用,可以在函数外部修改函数内部的变量。同时避免返回值的拷贝,从而提高性能,尤其是在返回大型对象时效果显著。

    注意,引用必须绑定有效对象:函数返回引用时,必须确保返回的引用绑定到一个有效的对象。避免返回局部变量的引用,因为局部变量在函数结束时会被销毁。

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

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

相关文章

Django序列化器详解:普通序列化器与模型序列化器的选择与运用

系列文章目录 Django入门全攻略&#xff1a;从零搭建你的第一个Web项目Django ORM入门指南&#xff1a;从概念到实践&#xff0c;掌握模型创建、迁移与视图操作Django ORM实战&#xff1a;模型字段与元选项配置&#xff0c;以及链式过滤与QF查询详解Django ORM深度游&#xff…

充电桩出口:跨国贸易的机遇与挑战之旅

在新能源浪潮席卷全球的今天&#xff0c;充电桩作为电动汽车的“加油站”&#xff0c;正逐渐从幕后走向台前。 而在这场跨国贸易的舞台上&#xff0c;充电桩的出口之路&#xff0c;既充满了诱人的机遇&#xff0c;也伴随着不小的挑战。 机遇&#xff0c;源自日益增长的全球市场…

免费听歌,电脑或手机免费听歌,落雪音乐安装详细步骤

近年来&#xff0c;由于资本的力量导致各种收费&#xff0c;看个电视想听歌都必须要付费了&#xff0c;否则你听不完整&#xff0c;吃相非常难看&#xff0c;特别是电视&#xff0c;吸血鬼式吸收各种会员费&#xff0c;各种APP也是铺天盖地的广告&#xff0c;渐渐迷失了自我&am…

两个螺旋面的交线

已知轴截面齿形&#xff0c;先得到螺旋面 然后在计算出对应的端面齿形 在用端面齿形来计算和另一个螺旋面的相交曲线。 三维验证这个方法可行&#xff01;

喜大普奔,AI绘画SD3终于开源了,AI绘画又添新利器!【附模型下载和安装包】

sd3终于开源了&#xff01; 没错就是stablediffusion 3.0版本&#xff01;这是stability迄今为止最先进最复杂图像生成模型。 这次开源的是medium版本&#xff0c;总共有三个型号的模型&#xff0c;下面我们来详细的说下sd3的功能特点以及不同型号区别、安装方法&#xff01;…

HTML静态网页成品作业(HTML+CSS)—— 家乡山西介绍网页(3个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;未使用Javacsript代码&#xff0c;共有6个页面。 二、作品演示 三、代…

专业设计师推荐的20条用户体验设计黄金准则

在当今的数字世界中&#xff0c;用户体验设计已经成为商业成功的关键因素。它可以实现或摧毁一个产品。今天&#xff0c;我们将讨论该领域的20个基本原则。这些用户体验设计原则不仅被顶级工厂设计师广泛使用&#xff0c;而且为您在设计过程中提供有价值的指导。 1. 以用户为中…

共绘财富与时间画卷,ATFX携手Haofa腕表,开启跨界新篇章

在当前激烈的市场竞争中&#xff0c;品牌创新和多元化、本地化发展已成为企业突破重围&#xff0c;赢得用户和市场份额的关键。作为差价合约行业领军品牌&#xff0c;ATFX勇于突破自我&#xff0c;为探索更多的市场可能性&#xff0c;通过跨界合作、联合营销的策略&#xff0c;…

物联网概念

物联网 物联网简介物联网体系结构物联网体系结构定义物联网体系结构设计原则物联网体系结构四层物联网体系结构感知控制层数据传输层数据处理层应用决策层 物联网关键技术感知标识技术网络与通信技术云计算技术安全技术 已有物联网相关应用架构无线传感器网络的体系结构EPC/UID…

同三维T80005JEHVA 4K视频解码器

同三维T80005JEHVA视频解码器 可解1路4K30HDMI/VGA/CVBS1路3.5音频 可解电台音频网络流&#xff0c;可同时解4个网络流&#xff0c;分割输出 可预设十个流&#xff0c;任意切换1路流输出 <!--[endif]----><!--[if !vml]--> <!--![endif]----> 介绍&…

逆向分析-Ollydbg动态跟踪Ransomware.exe恶意锁机程序

1.认识Ollydbg Ollydbg是一个新的动态追踪工具&#xff0c;将IDA与SoftICE结合起来的思想&#xff0c;Ring 3级调试器&#xff0c;非常容易上手&#xff0c;己代替SoftICE成为当今最为流行的调试解密工具了。同时还支持插件扩展功能&#xff0c;是目前最强大的调试工具。 Oll…

Java——面向对象进阶(二)

前言&#xff1a; 多态&#xff0c;包&#xff0c;final关键字&#xff0c;权限修饰符和代码块 文章目录 一、多态1.1 概念1.2 多态存在条件1.3 多态中调用成员的特点1.4 instanceof关键字 二、包三、权限修饰符四、final 关键字4.1 修饰类4.2 修饰方法4.3 修饰变量 五、代码块…

PHP开发的爱情盲盒交友系统网站源码

源码介绍 PHP开发的爱情盲盒交友系统网站源码 独立后台 源码截图 源码下载 PHP开发的爱情盲盒交友系统网站源码

CV预测:快速使用LeNet-5卷积神经网络

AI预测相关目录 AI预测流程&#xff0c;包括ETL、算法策略、算法模型、模型评估、可视化等相关内容 最好有基础的python算法预测经验 EEMD策略及踩坑VMD-CNN-LSTM时序预测对双向LSTM等模型添加自注意力机制K折叠交叉验证optuna超参数优化框架多任务学习-模型融合策略Transform…

vue3和ant-design 实现前端多种验证密码规则,最全的前端验证密码规则

1、小眼睛可以显示/隐藏明文密码&#xff08;无法用input typepassword&#xff0c;用css样式实现切换明文&#xff09; 2、输入长度统计&#xff08;不是自带的&#xff0c;用div写的&#xff0c;然后定位到框内的&#xff09; 3、每输入一个字符分别验证每一项规则&#xf…

神经网络 torch.nn---nn.LSTM()

torch.nn - PyTorch中文文档 (pytorch-cn.readthedocs.io) LSTM — PyTorch 2.3 documentation LSTM层的作用 LSTM层:长短时记忆网络层&#xff0c;它的主要作用是对输入序列进行处理&#xff0c;对序列中的每个元素进行编码并保存它们的状态&#xff0c;以便后续的处理。 …

藏品管理的发展历程

智能RFID藏品管理系统的发展是藏品管理领域的一项重大进步。它标志着从传统的手工记录方式向自动化、高效和智能化的管理方式的转变。通过RFID&#xff08;Radio Frequency Identification&#xff09;技术的应用&#xff0c;藏品管理系统实现了无接触、非视线范围内的数据读取…

绘唐3免费激活码

绘唐3免费激活码 绘唐3是一款网络绘画工具&#xff0c;可以用于绘制漫画和插画。你可以通过以下步骤下载绘唐3&#xff1a; 打开浏览器&#xff0c;搜索“绘唐阿祖”。在搜索结果中找到可靠的下载来源&#xff0c;例如官方网站或知名的软件下载网站。点击下载链接&#xff0c…

WinForm之TCP服务端

目录 一 原型 二 源码 一 原型 二 源码 using System.Net; using System.Net.Sockets; using System.Text;namespace TCP网络服务端通讯 {public partial class Form1 : Form{public Form1(){InitializeComponent();}TcpListener listener null;TcpClient handler null;Ne…

SAP BW:传输转换源系统-源系统映射关系

最近有朋友再问问我源系统映射关系怎么配置&#xff0c;想着写一个怕以后忘了。 简单说下这个是干嘛的&#xff0c;其实就是配置一个源系统到目标系统的一个映射&#xff0c;这样传输的时候才知道传过来的数据源要变成目标系统的数据源。 比如下图&#xff0c;在开发环境&…