C++中引用的基本内容

news2024/11/14 15:11:40

个人主页:平行线也会相交
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创
收录于专栏【C++之路】
在这里插入图片描述

引用,其实没啥特别的,就是起外号,或者说起小名。就比如说孙悟空就有很多外号,如齐天大圣、孙行者、斗战胜佛等等。虽然说可能有多种外号,但是这些外号都是指的是一个对象。下面来具体看一看到底什么是C++中的引用。

目录

  • 一、什么是引用
    • 1.1引用概念
      • 引用在Swap函数应用场景
      • 为指针定义别名
    • 1.2引用特性
  • 二、引用使用场景
    • 2.1引用做参数
    • 2.2引用做返回值
    • 2.3引用的几大作用
  • 三、常引用
  • 四、指针和引用的区别:

一、什么是引用

1.1引用概念

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

引用格式类型& 引用变量名(对象名)=引用实体

我们直接来举一个样例:
在这里插入图片描述
上图中ba的引用,而c又是b的引用,同时a、b、c其实指向的都是同一块内存空间
在这里插入图片描述
注意:我们不可以这样使用引用,int& b,这是一种错误写法。即:

在这里插入图片描述

引用在Swap函数应用场景

下面把引用应用到Swap函数上,请看:

void Swap(int& m, int& n)
{
	int tmp = m;
	m = n;
	n = tmp;
}
int main()
{
	int a = 10;
	int b = 20;
	cout << "a=" << a << endl;
	cout << "b=" << b << endl;
	Swap(a, b);
	cout << "a=" << a << endl;
	cout << "b=" << b << endl;
	return 0;
}

在这里插入图片描述
上面代码函数中的形参就是实参的一个引用,即m是a的引用,n是b的引用,改变m就是改变a,改变n就是改变b

为指针定义别名

引用还可以为指针定义别名,请看:
在这里插入图片描述
上图就是我们通过引用交换了两个变量的地址。

1.2引用特性

1.引用必须要进行初始化(即int& a;这种写法是错误的)。
2.一个变量可以有多个引用
3.引用一旦引用一个实体,则不能在继续引用其它实体。

同时,引用类型必须要与引用实体同一种类型

二、引用使用场景

2.1引用做参数

比如,我们刚刚的交换函数Swap就是利用的引用来做参数:

void Swap(int& m, int& n)
{
	int tmp = m;
	m = n;
	n = tmp;
}

2.2引用做返回值

下面是引用作传值返回。

int fun()
{
	static int n = 0;
	n++;
	return n;
}

int main()
{
	int ret = fun();
	return 0;
}

函数fun中的变量n存放在静态区中,出了局部域后栈帧不会销毁。但是在进行返回n的时候依然会生成临时变量。所以,引用作返回值的时候,不管变量n是局部变量还是静态区的变量又或者是全局变量。编译器都会生成一个临时变量。
倘若我们不想生成临时变量的话应该怎么半呢?这就是引用的另一大作用:即引用作返回值的时候不会生成临时变量
不生成临时变量的好处减少了拷贝,提高了效率。请看:
在这里插入图片描述
这里就是返回的n的别名(即返回的n的引用)
当我们的变量n是局部变量而非静态区变量的时候。请看:
在这里插入图片描述
我们已经知道这里返回的是局部变量n的别名,当把局部变量n的值给ret的时候,局部变量n所在的函数栈帧已经销毁了(即归还局部变量n所占空间的使用权),所以返回变量n的值理论上应该是不确定的。所以这里程序的运行结果应该有两种情况:

情况一:如果函数fun结束后,栈帧销毁,但是没有销毁栈帧,此时ret的结果侥幸是正确的。
情况二:如果函数fun结束后,栈帧销毁,清理栈帧了,那么此时ret的结果是随机的。
总之具体栈帧是否销毁还是要看编译器是如何处理的。

还有一种情况,请看:
在这里插入图片描述
首先,ret依然是n的别名(因为返回的是n的别名,而ret又是n的别名的别名,所以最后ret就是n的别名)。
其次我们发现程序运行结果就成了随机值了,这里的话就是刚刚上面提到的第二种情况了,即函数栈帧销毁后,清理了函数栈帧,所以打印出来的就是随机值。这里的话依然是和编译器的处理方式有关。

我们再来看一种情况:
在这里插入图片描述
这里打印出来依然是随机值,但是其具体原因与刚刚那种情况有些不同,这里rand()函数调用栈帧正好把fun()函数的栈帧覆盖了(说白了就是后面的函数栈帧覆盖了前面的函数栈帧),打印出来时随机值其实归根揭底还时栈帧被清理的问题。

在这里插入图片描述

2.3引用的几大作用

(1)引用作参数形参的改变可以改变实参),即引用作输入型参数;引用也可以作输出型参数提高效率。
(2)引用作返回值(当对象比较大的时候,与传值返回相比会极大的提高效率)。

三、常引用

常引用这里我们通过几段代码来引出来:

请看:
在这里插入图片描述
上述变量a经过const修饰后不可更改,既然a本身已经不可以进行更改了,所以就不要妄想通过引用b来更改a了这里强调的就是在引用的过程中,权限不可以放大。
再来看一段代码:
在这里插入图片描述
上述代码中强调的就是引用过程中权限可以平移但是权限不可以缩小。就比如说上述代码中的const int& b = x;这里缩小的并不是变量x的权限,而是缩小的引用b作为别名的权限
在这里插入图片描述
再来看这里,这里要强调的是x++是可以的,但是b++是不可以的,因为引用过程中引用b经过const修饰后权限被缩小了,这里虽然我们不能通过引用b来改变变量x,但是我们可以直接对变量x进行操作(即x++)就可以了。
再来看看const int& m = 10;这条语句,首先这条语句是正确的,引用b是常量10的别名,既然10是常量即不可更改,那么就需要const进行修饰。说白了这里就是给常量区别名。

下面我们先来看一下隐式类型转换的代码:
在这里插入图片描述
发生类型转换的时候中间会产生临时变量,所以只要发生类型转换,都会产生临时变量。

在这里插入图片描述
请再来看下段代码:
在这里插入图片描述
上述代码的话为什么int& c = a;报错了,但是const int&c = a;没有报错。
这里依然是临时变量的问题,请看下图:
在这里插入图片描述
注意类型转换才会产生临时变量,相同类型不会产生临时变量。下面我们来看一看为什么不同类型会产生临时变量而相同类型不会产生临时变量的原因:
在这里插入图片描述
上述代码之所以会打印出来就是因为发生了类型转换,产生了临时变量。当运算符两边的内容不是同一类型的时候会发生类型提升,提升有提升的规则,一般时范围小的向范围大的进行提升。上述变量j和变量i是如何进行比较的呢?因为这两个变量不是同一个类型,所以这里依然会生成一个临时变量,对变量i进行提升,这个提升的过程其实就是生成一个临时变量的问题,这个临时变量在这里是8个字节,即生成double类型的临时变量,然后依靠这个double类型的临时变量区和double类型的变量j进行比较。

下面我们再来举一个权限放大的例子:
在这里插入图片描述
在这里插入图片描述
此时引用ret1经过const修饰后,相当于权限的平移,就不会报错了。

再来看一看权限的平移和权限的缩小的例子:
在这里插入图片描述

四、指针和引用的区别:

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

好了,以上就是对C++中引用的一些基本内容。
就到这里吧,再见啦各位!!!

在这里插入图片描述

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

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

相关文章

基于Python实现个人手机定位分析

TransBigData是一个为交通时空大数据处理、分析和可视化而开发的Python包。本文就来用它实现个人手机定位分析&#xff0c;感兴趣的小伙伴可以了解一下 但其实交通时空大数据并不仅仅局限于交通工具产生的数据&#xff0c;我们的日常生活中也会产生大量的数据。比如我们的手机…

前端 百度地图绘制路线加上图片

使用百度官方示例的方法根据起终点经纬度查询驾车路线但是只是一个线路 <template><div class"transportInfo"><div id"mapcontainer" class"map">11</div><div class"collapse"><el-collapse v-mo…

CA(证书颁发机构)

CA 根证书路径/csk-rootca/csk-ca.pem&#xff1b; ~ 签发数字证书&#xff0c;颁发者信息&#xff1a;(仅包含如下信息) C CN ST China L BeiJing O skills OU Operations Departments CN CSK Global Root CA 1.修改证书的路径以及相关配置 vi /etc/pki/tls/op…

el-upload文件上传组件的封装

样式1 样式2 上传的格式 // annexUrl 数据格式如下[{"uid": 1682329534561,"name": "2023/04/24/273f36b860a74e79be3faed3ce20236f.pdf","suffix": ".pdf","url": "http://192.168.0.254:19000/annex/2023/…

JVM系列(十) 垃圾收集器之 Parallel Scavenge/Old

上篇文章我们讲解了单线程垃圾收集器 Serial/SerialOld &#xff0c;与之相对应的多线程垃圾收集器就是 Parallel Scavenge/Old&#xff0c; 本文我们讲解下多线程垃圾收集器 Parallel Scavenge/Old 垃圾收集器 新生代收集器&#xff1a; Serial、ParNew、Parallel Scavenge&…

数据库 | 什么是视图?怎么使用?什么是索引?

目录 一、视图 1 、视图概念 2、为什么要使用视图 3 、性能问题 4 、定义视图 5、查看视图 6、删除视图 二、索引 1、引入索引的问题 2、索引是什么 3、索引为什么选择b树 一、视图 1 、视图概念 视图&#xff08;View&#xff09;是一种虚拟存在的表&#xff0c;对…

【DRF配置管理】如何建立完善的DRF自带接口docs文档

原文作者&#xff1a;我辈李想 版权声明&#xff1a;文章原创&#xff0c;转载时请务必加上原文超链接、作者信息和本声明。 DRF应用和管理 【DRF配置管理】Django使用DRF框架 【DRF配置管理】如何实现JWT认证 【DRF配置管理】如何在视图函数配置参数(一) 【DRF配置管理】如何…

okcc呼叫问题的解决方法(建议收藏)

很多客户开始使用OKCC呼叫中心系统&#xff0c;运营经常遇到的问题是呼叫打不通&#xff0c;无话单&#xff0c;呼叫秒挂&#xff0c;语音提示"您没有使用业务的权限"等等异常情况&#xff0c;而且反馈线路正常&#xff0c;使用呼叫系统拨打就是呼不通。 OKCC系统…

史上最烂 spring aop 原理分析

盗引中篇spring aop spring aop: jdk 动态代理和 cglib 动态代理的特点、区别、使用方式、原理及各自对反射的优化、二者在 spring 中的统一、通知顺序、从 Aspect 到 Advisior、静态通知调用、动态通知调用。 版本 jdk&#xff1a;8spring&#xff1a;5.3.20spring boot&…

华为OD机试(20222023)真题目录 + 考点 + 复盘思路

大家好&#xff0c;我是哪吒。 本专栏包含了最新最全的华为OD机试真题&#xff0c;有详细的分析和Java代码解答。已帮助1000同学顺利通过OD机考&#xff0c;发现新题目&#xff0c;随时更新。 以下为华为OD机试真题题库。 1、华为OD机试真题&#xff08;Java&#xff09;&am…

创建型模式-原型模式

原型模式 介绍 用一个已经创建的实例作为原型&#xff0c;通过复制该原型对象来创建一个和原型对象相同的新对象 结构 原型模式包含如下角色&#xff1a; 抽象原型类&#xff1a;规定了具体原型对象必须实现的的 clone() 方法。具体原型类&#xff1a;实现抽象原型类的 cl…

Linux文本处理三大利器Grep、AWK、Sed

写在前面 Linux三剑客是文本处理工具&#xff0c;它们可以帮助我们快速、高效地对文本进行处理。其中包括了grep、awk、以及sed这三个强大的命令行工具。 Linux 三剑客主要作用: grep&#xff0c;它可以根据正则表达式查找相关内容并打印对应的数据。awk&#xff0c;它可以根…

redhat8配置vsftpd服务

目录 一、匿名访问模式 1.1、ftp服务器端修改配置&#xff08;配置文件&#xff1a;/etc/vsftpd/vsftpd.conf&#xff09; 1.2 修改ftp目录的权限 1.3 设置selinux服务对ftp服务的访问规则策略为允许 1.4 防火墙添加ftp服务 1.5 测试 二、本地用户模式 2.1 服务端修改配…

6、什么是类型断言?

虽然 TypeScript 很强大&#xff0c;但有时还不如我们了解一个值的类型方便&#xff0c;这时候我们更希望 TypeScript 不要帮我们进行类型检查&#xff0c;而是交给我们自己来&#xff0c;所以就用到了类型断言。类型断言有点像是一种类型转换&#xff0c;它把某个值强行指定为…

Vue收集表单数据学习笔记

收集表单数据 v-model双向数据绑定&#xff0c;收集的是input框的value&#xff0c;单选按钮不存在value&#xff0c;就像代码中的男女选项&#xff0c;即使绑定性别v-model“sex”&#xff0c;控制台依然不能接收性别的值&#xff0c;因为没有value值&#xff0c;&#xff0c…

python 第二章——数据类型详解

文章目录 前言一、什么是数据类型1.变量2.注释 二、数字三、字符串四、布尔五、列表六、元组七、集合八、字典总结 前言 本系列教程目录&#xff0c;可点击这里查看&#xff1a;Python教程目录 学习一门编程语言&#xff0c;第一件事就应该是熟练掌握这门编程语言的基本数据类…

[Java]JavaWeb开发中的MVC设计模式

一、有关Java Web与MVC设计模式 学习过基本Java Web开发的人都已经了解了如何编写基本的Servlet&#xff0c;如何编写jsp及如何更新浏览器中显示的内容。但是我们之前自己编写的应用一般存在无条理性&#xff0c;对于一个小型的网站这样的编写没有任何问题&#xff0c;但是一但…

MCDF代码详解,mcdf_rgm_pkg.sv代码超详细注释

寄存器模块代码详解 好戏开始: `include "param_def.v" package mcdf_rgm_pkg; import uvm_pkg::*; `include "uvm_macros.svh" import reg_pkg::*; //具有uvm_reg类型的专用寄存器描述[write-red-reg] class ctrl_reg extends uvm_r…

机器人教学中游戏化课程案例尝试

本文内容严格按创作模板发布&#xff1a; 2023年LPL春季赛季后赛正在火热进行中&#xff0c;你们心中的总冠军是哪支队伍呢&#xff1f;作为热爱游戏的程序猿&#xff0c;一起来聊聊你那些有意义的游戏开发经历吧&#xff01; 游戏化ROS机器人课程的优势有以下七点&#xff1a…

第3章-运行时数据区

此章把运行时数据区里比较少的地方讲一下。虚拟机栈&#xff0c;堆&#xff0c;方法区这些地方后续再讲。 转载https://gitee.com/youthlql/JavaYouth/tree/main/docs/JVM。 运行时数据区概述及线程 前言 本节主要讲的是运行时数据区&#xff0c;也就是下图这部分&#xff0c…