初始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、读操作 总体代…...

使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...

DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...

基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建
华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...

selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...