C++之引用的介绍

news2024/10/6 6:49:49

目录

前言

引用

1.引用的概念

2.引用特性

3.引用的权限

4. 使用场景

4.1 做参数

4.2 做返回值

5.引用和指针的区别


前言

相信大家都看过水浒传,里面的英雄人物除了自己的名字外都有自己的称号,比如:花和尚——鲁智深,豹子头——林冲……,这里我们发现我们人都有自己的别名,那么变量呢,其实变量也有给自己取别名的功能,那么小编今天就给大家介绍一下这个功能。


引用

1.引用的概念

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空
间,它和它引用的变量共用同一块内存空间
首先给大家讲解一下类的声明与定义方式:
类型& 引用变量名(对象名) = 引用实体;
那么这里小编简单的给大家演示一下:
#include<iostream>
using namespace  std;
int main()
{
	int a = 10;
	int& c=a;//这里指的是c是a的引用类型
	cout << c << endl;
}
此时我们看一下输出c的结果是:

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

2.引用特性

1. 引用在定义时必须初始化
2. 一个变量可以有多个引用
这里小编简单的给大家演示一下:
#include<iostream>
using namespace  std;
int main()
{
	int a = 10;
	int& c=a;
	int& b = a;
	int& d = a;
	cout << c << endl;
	cout << b << endl;
	cout << d << endl;
}

 这里我们运行一下:

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

3.引用的权限

对于引用的权限,我们只能进行权限的平移或者缩小,不能进行放大操作,那么这里具体指的是什么意思呢?这里大家跟着我一起理解一下。

这里我们要使用到const关键字,这里的作用就是让变量具有常数性质,也就是我们不能够去改变此变量的权限,也就是将一个变量的权限缩小了。

#include<iostream>
using namespace  std;
int main()
{
	int a = 10;
	int& c=a;//权限平移
	const int& d = a;//权限缩小
	cout << c << endl;
	cout << d << endl;
}

这里我们运行一下看看有没有什么问题:

 那么这里我们再看看权限放大会出现什么情况:

#include<iostream>
using namespace  std;
int main()
{
	const int a = 10;
	int& b = a;
}

这里我们运行看看结果:

 这里我们看到这里出现了问题,所以我们这里的是不能进行权限放大的操作的.

4. 使用场景

既然我我们已经学习

4.1 做参数

#include<iostream>
using namespace  std;
void Swap(int& left, int& right)
{
	int temp = left;
	left = right;
	right = temp;
}
int main()
{
	int a = 10;
	int b = 20;
	Swap(a, b);
	cout << a << endl;
	cout << b << endl;
	return 0;
}

这里我们用引用类型写一个交换函数,这里我们看结果:

4.2 做返回值

#include<iostream>
using namespace  std;
int& Count()
{
	static int n = 0;
	n++;
	return n;
}
int main()
{
	cout << Count()<< endl;
	return 0;
}

这里我们返回值是n的引用类型,所以我们得到的是和n使用同一块地址的引用类型,该返回结果如下:

 这里我们再看一个例子:

#include<iostream>
using namespace  std;
int& Add(int a, int b)
{
	int c = a + b;
	return c;
}
int main()
{
	int& ret = Add(1, 2);
	Add(3, 4);
	cout << "Add(1, 2) is :" << ret << endl;
	return 0;
}

这里按照函数逻辑,大家可能都知道这里我们得到的值是3,那么我们这里运行一下:

 这里我们发现我们虽然我们接收的是我们第一次函数的返回值,但是我们得到的是第二次调用的返回值,这是什么原因呢?大家接下来请听小编细细给大家解释:

首先我们要明白,这里的返回值是变量c的别名,这里我们由于我们的ret变量也是引用类型,所以这里我们ret也是变量c的别名,所以我们ret实际上和c共用同一块空间,但是这里我们需要考虑一点就是当函数结束调用后,我们变量c是会被销毁的,但是这里ret依然记录的是原先c变量的地址,那么我们这里就需要考虑编译器调用结束后是否会马上对函数栈帧进行清理,如果没进行清理那么该得到的值将会恰好正确,但是如果进行了清理那么我们得到的值就是随机的。

那么这里很明显,这里我们并没有对函数栈帧进行清理,那么我们又是怎么得到:7这个值的呢?这里我们由于ret记录的是变量c的地址,由于我们的编译器没有及时清理函数栈帧,所以我们得到ret地址的值是5,由于再次调用同个函数,由于这次调用的函数和之前的函数是同一个函数,所以我们ret的地址和该函数中变量c是恰好是同一个地址,所以ret的内容也就是此时变量c的内容,所以得到了7这个值,那么如果我们调用了其他函数后我们ret的值是多少呢?

#include<iostream>
using namespace  std;
int& Add(int a, int b)
{
	int c = a + b;
	return c;
}
int main()
{
	int& ret = Add(1, 2);
	printf("haha");
	cout << "Add(1, 2) is :" << ret << endl;
	return 0;
}

运行之后看结果:

 这里就很明显的说明了ret是变量c引用,但是c是其他函数的函数栈帧中。

所以这里我们对于其使用做一个小小的总结:

1.基本任何场景都可以用引用传参。

2.谨慎使用引用做返回值,出了作用域,对象不在了,就不能用引用返回,还在就可以使用引用返回

既然这里我们涉及到引用类型做形参以及返回类型,那么对于我们正常的传参和返回,它的优势又在哪里呢?

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

5.引用和指针的区别

语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。在底层实现上实际是有空间的,因为引用是按照指针方式来实现的。

这里我给大家罗列一些其区别:

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

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

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

相关文章

centOS7.9安装nginx

此示例为安装nginx-1.20.1 &#xff08;小版本无差别&#xff09; 安装过程 sftp上传nginx-1.20.1.tar.gz文件到机器&#xff08;在root目录下&#xff09; #cd /usr/local/nginx/sbin #./nginx -V (查看版本&#xff0c;如果已经有安装过的话会出现版本号) 切换到loca…

k8s 源码分析 informer篇

之前介绍过informer的流程&#xff0c;文章在 informer介绍。今天梳理一下他的源码和流程。 一、概念 什么是 Informer informer 是 client-go 中的核心工具包&#xff0c;informer 其实就是一个带有本地缓存和索引机制的&#xff0c;可以注册 EventHandler 的 client 本地缓存…

L2-1 堆宝塔

堆宝塔游戏是让小朋友根据抓到的彩虹圈的直径大小&#xff0c;按照从大到小的顺序堆起宝塔。但彩虹圈不一定是按照直径的大小顺序抓到的。聪明宝宝采取的策略如下&#xff1a; 首先准备两根柱子&#xff0c;一根 A 柱串宝塔&#xff0c;一根 B 柱用于临时叠放。把第 1 块彩虹圈…

Linux下使用Mysql 第一天

目录 安装mysql 更改账户名和密码 启动/关闭mysql mysql的基本操作 数据库CURD 创建数据库 查看数据库 修改数据库 删除数据库 表的CURD 创建表 查看表 修改表 删除表 表数据的CURD create数据 Retrieve数据 update数据 delete数据 DML和DDL的区别&#xf…

波形生成:均匀和非均匀时间向量

波形生成—— 脉冲、chirp、VCO、正弦函数、周期性/非周期性和调制信号 使用 chirp 生成线性、二次和对数 chirp。使用 square、rectpuls 和 sawtooth 创建方波、矩形波和三角形波。 如需了解此处未显示的其他无线波形生成功能&#xff0c;请参阅无线波形发生器 (Communicat…

【腾讯云-2】极简搭建边缘集群

1 创建 流程和https://blog.csdn.net/qq_47058489/article/details/130347795差不多&#xff0c;可参考 查看基本信息&#xff1a; 创建边缘集群的过程中会初始化master&#xff0c;说明包含一个托管master节点 但是没有其他节点 2 开启节点远程登录 通过 SSH 的方式远…

JavaScript模块化开发

目录&#xff1a; 1 认识模块化开发 2 CommonJS和Node 3 require函数解析 4 AMD和CMD&#xff08;了解&#xff09; 5 ESModule用法详解 6 ESModule运行原理 模块化不是两个不同的js文件直接导入到某个页面中的&#xff0c;因为这两个文件只要有相同的变量或函数&#xf…

html学习(标签、css、选择器)

认识HTML HTML是HyperText Markup Language的缩写&#xff0c;中文名为超文本标记语言。它是一种用来创建网页的标准标记语言&#xff0c;由标签&#xff08;tag&#xff09;和文本构成&#xff0c;用于描述网页的结构和内容。HTML文档可以被浏览器解析并呈现出网页的内容和样…

方向梯度直方图(Histogram of Oriented Gradient)

1.方向梯度直方图&#xff08;Histogram of Oriented Gradient&#xff09; 笔记参考&#xff1a;HOG特征提取 笔记参考&#xff1a;一文讲解方向梯度直方图&#xff08;hog&#xff09; 笔记参考&#xff1a;Histogram of Oriented Gradients (HOG) | By Dr. Ry Stemplicity …

【Java-01】深入浅出匿名对象 , 继承 , 抽象类

主要内容 面向对象回顾 匿名对象介绍 面向对象特征 - 继承 抽象类的使用 模板设计模式 1 面向对象回顾 面向对象的核心思想是什么 ? 用代码来模拟现实生活中的事物 , 比如学生类表示学生事物 , 对象表示的就是具体的学生 , 有了类就可以描述万千世界所有的事物了 现有的…

【PaddleNLP-kie】关键信息抽取2:UIE模型做图片信息提取全流程

文章目录 本文参考UIE理论部分step0、UIEX原始模型使用网页体验本机安装使用环境安装快速开始 step1、UIEX模型微调&#xff08;小样本学习&#xff09;微调模型对比step2、服务化部署step3、提升推理速度模型量化更换模型fast-tokenizer提高batch_size&#xff08;没用&#x…

第十一章 组合模式

文章目录 前言一、组合模式基本介绍二、UML类图三、完整代码抽象类&#xff0c;所有类都继承此类学校类以父类型引用组合一个学院类学院类以父类型引用组合一个专业类专业类&#xff0c;叶子节点&#xff0c;不能再组合其他类测试类 四、组合模式在JDK集合的源码分析五、组合模…

51单片机(一)软硬件环境和单片机介绍

❤️ 专栏简介&#xff1a;本专栏记录了从零学习单片机的过程&#xff0c;其中包括51单片机和STM32单片机两部分&#xff1b;建议先学习51单片机&#xff0c;其实STM32等高级单片机的基础&#xff1b;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 &#xff1a;适用于想要…

delta.io 参数 spark.databricks.delta.replaceWhere.constraintCheck.enabled

总结 默认值true 你写入的df分区字段必须全部符合覆盖条件 .option("replaceWhere", "c2 == 2") false: df1 overwrite tb1: df1中每个分区的处理逻辑: - tb1中存在(且谓词中匹配)的分区,则覆盖 - tb1中存在(谓词中不匹配)的分区,则append - tb1中不存…

热闹之后,香港是否会成为Web3的“应许之地”?

出品&#xff5c;欧科云链研究院 作者&#xff5c;Jason Jiang 自从2022年底有关虚拟资产在港发展的政策宣言发布后&#xff0c;香港始终是Web3世界的焦点。当港府官员频繁现身以鼓励Web3创新发展&#xff0c;当数以万计的Web3 Builders时隔三年再次聚首香江&#xff0c;当传…

密码学报Latex模板使用

密码学报Latex模板使用 首先从密码学报下载模板 然后注册overleaf账号 创建新项目&#xff0c;把.zip包导入 修改编译器为XeLaTeX 然后点击重新编译即可

信息安全复习六:公开密钥密码学

一、章节梗概 1.公开密钥密码模型的基本原理 2.两个算法&#xff1a;RSA&D-H算法 主要内容 1.对称密钥密码的密钥交换问题 2.公钥密码模型的提出 3.设计公钥密码的基本要求 4.数字签名 5.RSA算法 6.公钥密码的特征总结 二、对称密钥密码 对称加密算法中&#xff0c;数据…

SpringCloud --- Feign远程调用

一、RestTemplate问题 先来看我们以前利用RestTemplate发起远程调用的代码&#xff1a; 存在下面的问题&#xff1a; 代码可读性差&#xff0c;编程体验不统一参数复杂URL难以维护 Feign是一个声明式的http客户端&#xff0c;官方地址&#xff1a;GitHub - OpenFeign/feign:…

程序员如何提高代码能力

目录 程序员如何提高代码能力——C语言方向阅读优秀的代码不断练习学习新技术与他人合作不断反思和改进 程序员如何提高代码能力——C语言方向 C 是一种功能强大的编程语言&#xff0c;广泛应用于操作系统、数据库、游戏开发等领域。而要成为一名优秀的 C 程序员&#xff0c;不…

动力节点Vue笔记④ Vue与Ajax

四、Vue与AJAX 4.1 回顾发送AJAX异步请求的方式 发送AJAX异步请求的常见方式包括&#xff1a; 原生方式&#xff0c;使用浏览器内置的JS对象XMLHttpRequest const xhr new XMLHttpRequest()xhr.onreadystatechange function(){}xhr.open()xhr.send() 原生方式&#xff0…