初始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、读操作 总体代…...
深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...
破解路内监管盲区:免布线低位视频桩重塑停车管理新标准
城市路内停车管理常因行道树遮挡、高位设备盲区等问题,导致车牌识别率低、逃费率高,传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法,正成为破局关键。该设备安装于车位侧方0.5-0.7米高度,直接规避树枝遮…...
鸿蒙(HarmonyOS5)实现跳一跳小游戏
下面我将介绍如何使用鸿蒙的ArkUI框架,实现一个简单的跳一跳小游戏。 1. 项目结构 src/main/ets/ ├── MainAbility │ ├── pages │ │ ├── Index.ets // 主页面 │ │ └── GamePage.ets // 游戏页面 │ └── model │ …...
怎么开发一个网络协议模块(C语言框架)之(六) ——通用对象池总结(核心)
+---------------------------+ | operEntryTbl[] | ← 操作对象池 (对象数组) +---------------------------+ | 0 | 1 | 2 | ... | N-1 | +---------------------------+↓ 初始化时全部加入 +------------------------+ +-------------------------+ | …...
