初始C++(三):引用
文章目录
- 一.引用的概念
- 二.引用的使用
- 1.引用作为输出型参数
- 2. 引用作为函数返回值
- 3.const引用
 
- 三.引用的一些小问题
- 四.引用和指针
- 五.引用和指针的区别
 
一.引用的概念
引用的作用是给一个已经存在的变量取别名,编译器不会为引用变量开空间,引用变量和被他引用的变量共用一块空间。
二.引用的使用
//类型& 引用变量名(对象名) = 引用实体;
int i = 10;
int& j = i;//j就是i的引用,也可以说j就是i的别名
上面的i和j公用一块空间:
 
完全可以认为i,j代表的是一个东西。比如对i++使i变成11的时候,j也会变成11:
 
1.引用作为输出型参数
在我们学C语言的时候,应该遇到过交换函数,就是要求写一个函数来交换两个变量的值,当时是这样写的:
void Swap(int* i, int* j)
{int tmp = *i;*i = *j;*j = tmp;
}
因为函数的形参是实参的一份临时拷贝,也就是说形参的改变不会影响到实参的变化,所以这里我们要传递需要改变的两个变量的地址,这样在Swap函数里解引用才能找到需要改变的两个变量的值。
 但是每次使用都要传地址,这样显得就非常麻烦,于是C++里的引用在这里就派上了大用场,现在这个交换函数可以这样写:
void Swap1(int& i, int& j)
{int tmp = i;i = j;j = tmp;
}
int main()
{Swap1(10,20);return 0;
}
这里的形参i,j不是实参的临时拷贝了,而是两个实参的别名,对两个别名的交换就可以认为是对实参两个变量的交换。
2. 引用作为函数返回值
首先看这样的一段代码:
int f()
{int n = 0;n++;return n;
}int main()
{int ret = f();return 0;
}
来了解一下n这个值是怎么传给ret的:
 1.在f()这个函数运行完之前变量n的值首先会拷贝到一个临时变量中。
 2.然后f()函数结束,这个函数的空间被销毁
 3.最后临时变量的值赋值给变量ret.
小知识点:临时变量
如果需要拷贝的值很小,临时变量可以是用寄存器来代替,如果很大,比如像一个结构体,那这个临时变量是在f()的上层函数中直接帮你开辟好的,这个上层函数可以认为是调用f()函数的函数,临时变量具有常性,可以理解为被const修饰了一样。
在函数值返回,隐式/显式类型转换的时候都会产生临时变量
int a = 10;
cout << (double)a << endl;//这里是显式转换
double b = a;//这里是隐式转换
接下来在看一段代码:
int f1()
{static int n = 0;n++;return n;
}int main()
{int ret = f1();return 0;
}
虽然这里的n变成了静态的变量,储存在静态区,f()函数销毁后n不会被销毁,但是计算机仍然会将n拷贝到一个临时变量中,然后再由这个临时变量返回给ret.
这里的变量n完全可以不用进行拷贝,所以上面的代码可以进行一些优化:
int& f1()//将值返回变成引用返回
{static int n = 0;n++;return n;
}int main()
{int ret = f1();return 0;
}
如果将值返回变为引用返回,返回的值将不再是临时变量,而是n的引用,也可以说返回的就是n这个变量。这样就可以减少中间拷贝的过程。
 所以在返回的变量在函数销毁的时仍然存在的情况下,返回值就可以用引用返回。
明白了这一点,还可以写这样的一种代码:
//定义一个数组结构体
typedef struct Array
{int a[10];
}Array;//定义一个函数用来寻找数组中第i个位置上的值
int& at(Array& ay, int i)
{assert(i < 10);return ay.a[i];  //形参用引用来接收,ay.a[i]中的ay是main函数中定义的那个数组的别名//返回值用引用,返回的就是main函数中定义的那个数组的别名
}int main()
{Array ay;    //定义一个结构体for (int i = 0; i < 10; i++){//既然返回值就是自己定义的结构体里的数组,//所以对其赋值也是完全可以at(ay, i) = i;}for (int i = 0; i < 10; i++){cout << at(ay, i) << ' ';}cout << endl;return 0;
}

通过这段代码,引用返回不但可以减少拷贝,还可以对返回值进行修改。这里的at函数返回的就是数组里第i个元素,at(ay, i) = i就可以认为对第i个元素进行赋值。
3.const引用
先说结论:指针/引用在初始化和赋值的时候只能权限保持和权限缩小,不能权限放大。
权限放大:
int main()
{const int a = 10;int& b = a;return 0;
}
变量a的类型是const int说明它具有常属性,也就是不能被改变,但是a的别名b的类型是int反而可以改变了,这就是所谓的权限放大。如果这样写代码,编译器会报错的。
权限保持/权限缩小:
int main()
{//权限保持const int a = 10;const int& b = a;//权限缩小int x = 10;const int& y = x;return 0;
}
权限保持和缩小是没问题的。指针在这一块和引用是一样的,这里就不再复述了。
三.引用的一些小问题
- 引用类型必须和引用实体是同种类型的
- 引用在定义时必须初始化
- 一个变量可以有多个引用
- 引用一旦引用一个实体,再不能引用其他实体
四.引用和指针
在语法概念这个层次上引用是不开空间的,而指针是需要开空间的。接下来通过代码的汇编指令,看看引用和指针有没有区别:
int main()
{int a = 10;int* pa = &a;*pa = 20;int& ra = a;ra = 20;return 0;
}

虽然你可能不动这些指令是什么,但你只要看指针和引用有没有区别就行。
 不难发现,引用和指针在底层的指令是一模一样的。所以说,虽然表面上引用和指针是两码事,但在底层,引用其实就是指针。
五.引用和指针的区别
- 引用概念上定义一个变量的别名,指针存储一个变量地址。
- 引用在定义时必须初始化,指针没有要求
- 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体
- 没有NULL引用,但有NULL指针
- 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节,64位平台下占8个字节)
- 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
- 有多级指针,但是没有多级引用
- 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
- 引用比指针使用起来相对更安全
相关文章:
 
初始C++(三):引用
文章目录一.引用的概念二.引用的使用1.引用作为输出型参数2. 引用作为函数返回值3.const引用三.引用的一些小问题四.引用和指针五.引用和指针的区别一.引用的概念 引用的作用是给一个已经存在的变量取别名,编译器不会为引用变量开空间,引用变量和被他引…...
 
【前端】参考C站动态发红包界面,高度还原布局和交互
最近有些小伙伴咨询博主说前端布局好难,其实都是熟能生巧! 模仿C站动态发红包界面,cssdiv实现布局,纯javascript实现交互效果 目录 1、界面效果 2、界面分析 2.1、整体结构 2.2、标题 2.3、表单 2.4、按钮 3、代码实现 3.…...
 
VR全景带你浪漫“狂飙”情人节,见证甜蜜心动
当情人节遇上VR,足以让情侣过一个难忘的情人节。马上情人节就要到了,大家是不是还在绞尽脑汁的想着,如何和另一半过一个浪漫的情人节呢?老套的剧情已经不能吸引人了,让我们看看VR全景给情人节带来了哪些不同的体验吧&a…...
 
Linux系统安全之iptables防火墙
目录 一.iptables防火墙基本介绍 二.iptables的四表五链 三.iptables的配置 1.iptables的安装 2.iptables防火墙的配置方法 四.添加、查看、删除规则 1.查看(fliter)表中的所有链 iptables -L 2.使用数字形式(fliter)表所有链 查看输出结果 iptables -nL 3.清空表中所…...
【C#基础】C# 变量与常量的使用
序号系列文章1【C#基础】C# 程序通用结构2【C#基础】C# 基础语法解析3【C#基础】C# 数据类型总结文章目录前言一. 变量(variable)1,变量定义及初始化2,变量的类别3,接收输出变量二. 常量(constantÿ…...
 
[ 常用工具篇 ] CobaltStrike(CS神器)基础(一) -- 安装及设置监听器详解
🍬 博主介绍 👨🎓 博主介绍:大家好,我是 _PowerShell ,很高兴认识大家~ ✨主攻领域:【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 🎉点赞➕评论➕收藏 养成习…...
 
Redis集群
Redis集群 本章是基于CentOS7下的Redis集群教程,包括: 单机安装RedisRedis主从Redis分片集群 1.单机安装Redis 首先需要安装Redis所需要的依赖: yum install -y gcc tcl然后将课前资料提供的Redis安装包上传到虚拟机的任意目录ÿ…...
 
00---C++入门
1. C关键字(C98) C总计63个关键字,C语言32个关键字 2. 命名空间 在C/C中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进…...
 
Spring-事务2
文章目录前言一、事务的特性(ACID)二、事务的隔离级别三、spring中的事务平台事务管理器.事务定义ISOLation_XXX:**事务隔离级别.**PROPAGATION_XXX:**事务的传播行为**.事务状态关系:四、使用XML文件配置事务1、 搭建…...
 
Windows Git Bash 配置
Windows Git Bash 配置 本文参考的文章: 在 Windows 的 Git Bash 中使用包管理器 - iris (ginshio.org)Git bash 安装 pacman & Windows 解压 zst 文件 | 伪斜杠青年 (lckiss.com) 一、Git的安装 Git 的安装应该是都会的,但还是应该说以下&#…...
java代码整合kettle9.3实现读取表中的数据,生成excel文件
java代码整合kettle9.3实现读取表中的数据,生成excel文件 1.简介 本次使用java代码整合kettle9.3版本,数据库使用mysql。 2.jar包导入 项目需要依赖部分kettle中的jar包,请将这部分jar包自行导入maven仓库。 <dependency><groupId…...
 
分享微信点餐小程序搭建步骤_微信点餐功能怎么做
线下餐饮实体店都开始摸索发展网上订餐服务。最多人选择的是入驻外卖平台,但抽成高,推广还要另买流量等问题,也让不少商家入不敷出。在这种情况下,建立自己的微信订餐小程序,做自己的私域流量是另一种捷径。那么&#…...
 
4、数组、切片、map、channel
目录一、数组二、切片三、map四、channel五、引用类型一、数组 数组: 数组是块连续的内存空间,在声明的时候必须指定长度,且长度不能改变所以数组在声明的时候就可以把内存空间分配好,并赋上默认值,即完成了初始化数组…...
270 uuid
270 uuid 用途 For the creation of RFC4122 UUIDs 可靠性 10000 星星 适应于浏览器或者服务器 官网链接 https://www.npmjs.com/package/uuid https://github.com/uuidjs/uuid 基本使用 import { v4 as uuidv4 } from uuid; uuidv4(); // ⇨ 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3d…...
 
2023最新简历模板免费下载
下面分享5个简历模板网站,免费下载,建议收藏! 2023用最漂亮的简历模板,让面试官眼前一亮。 1、菜鸟图库 个人简历模板|WORD文档模板免费下载 - 菜鸟图库 菜鸟图库除了有超多设计类素材之外,还有很多办公类素材&#…...
 
【CSS】元素居中总结-水平居中、垂直居中、水平垂直居中
【CSS】元素居中一、 水平居中1.行内元素水平居中(1)text-align2.块级元素水平居中2.1 margin(1)margin2.2布局(1)flex justify-content(推荐)(2) flexmargin…...
spring实现AOP
文章目录前言一、AOP的底层实现原理二、AOP的两种开发模式1.使用xml配置文件1.1 添加AOP依赖1.2 创建UserService1.3创建UserServiceImpl1.4创建通知类1.5 创建applicationContext.xml(添加aop约束)1.6 测试2.使用注解开发2.1 创建bean.xml文件配置注解方…...
neovim搭建cpp环境
文章目录Windowns下NeoVim搭建cpp环境NeoVim安装插件vim-plugindentLinevim-airlinectagstagbarcoc.vimWindowns下NeoVim搭建cpp环境 在开发过程中习惯在DIE环境中使用vim作为编辑器,在单独的编辑器也常使用gvim图形化编辑器。最近看到NeoVim的特性及兼容性方面不输…...
SpringBoot AES加密 PKCS7Padding 模式
AES 简介:DES 全称为Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1977年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS) AES 密码学中的高级加密标准(Advan…...
 
按键输入驱动
目录 一、硬件原理 二、添加设备树 1、创建pinctrl 2、创建节点 3、检查 编译复制 三、修改工程模板编辑 四、驱动编写 1、添加keyio函数 2、添加调用 3、驱动出口函数添加释放 4、添加原子操作 5、添加两个宏定义 6、初始化原始变量 7、打开操作 8、读操作 总体代…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
 
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
 
springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
 
ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
 
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
 
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
