013 - C++引用

本期我们要讲的是 C++ 中的引用

上期我们讨论了指针,如果你没有看过那期内容,你一定要回去看看,因为引用实际上只是指针的扩展,你至少需要在基本层面上理解指针是如何工作的,然后才能继续学习本期的内容,本期内容是指针那一期的链接。

先了解这些

指针引用 是被大量翻来覆去提及的两个关键字,在 C++ 语言和其他语言中,它们本质上是一样的。

没错,指针和引用在计算机中做的事情几乎是一样的,从语义上说,我们如何使用和书写它们,有一些细微的区别,但从根本上来讲,引用只是指针的伪装,它们只是在指针的语法糖,它可以让程序更容易阅读,更容易被理解。

顾名思义,引用是一种我们引用现有变量的方式,不像指针。你可以创建一个新的指针变量或类似的东西,设它等于零,但是你不能对引用这样做,因为引用必须 “引用” 已经存在的变量。引用本身并不是新的变量,它们并不占用内存,它们没有真正的存储空间,它们不像典型的变量,因为它们是作为一个变量的引用而存在的。

下面我会举几个不同的例子来说明,例子会尽量简短一些,因为引用并不复杂,学习如何使用它们的最好方法就是随着系列的进行开始使用它们,后面我们会一直使用它们,你会看到一些很好的使用方式。

这就是引用

[igNo8b.png

我有一个变量,记作 a,我让它等于 5,它是一个整数,我给这个变量创建一个引用,我可以输入变量的类型,后面跟着 & 符号,注意 & 符号实际上是变量声明的一部分。

如果你看过指针那一期,你会知道我们可以使用 & 符号获取现有变量的内存地址,这里不一样,因为 & 符号实际 不在类型旁边,它只是类型的一部分,要注意区别,因为很多人只要看到 &,就认为都是引用,或者都是取地址,其实具体是啥取决于上下文,在当前例子中,因为它在类型的旁边,所以它是一个引用。

我们继续解释代码,我将基命名为 ref, 并将其值设为 a,然后这里就不需要其他奇怪的运算符了,我们只是让它等于一个现有的变量就可以了。

我们现在创造了一个叫做 别名 的东西,因为这个 ref “变量” ,——我说的 “变量” 是带引号的,因为它不是一个真正的变量,这只是一个引用,ref 变量实际上不存在,它只存在于我们的源代码中。如果你现在编译这段代码,你不会得到两个变量 a 和 ref,你只会得到 a。

我们现在能做的是,我们可以使用 ref 就像它就是 a,如果我们设 ref 等于 2,然后打印 a,你会发现 a 的值变为了2。

[igNSfd.png

因为 ref 就是 a,我们只是给 a 起了个别名,在这种情况下,我们的引用不是一个指针或其他类似的东西,编译器不需要实际创建一个新变量,如果你编译代码,这代码就相当于你设置了 a = 2,我们就是这么做的,因为如果给变量起一个别名的话,某些情况下我们的代码逻辑会更简单一些。

让我们尝试一些更复杂的东西。

我们定义一个函数 Increment,让整型变量递增。你觉的下面的写法会实现这个功能吗?

[igNsFq.png

并不能。

我们调用 Increment 函数,将 a 作为参数传递进去,你可以看到我们井没有把它作为一个指针或者引用等类似的东西传进去,它会拷贝这个值 5 复制到函数中,复制会创建一个全新的变量 value,这就是程序中发生的事情,如果运行代码我们可以看到打印出的值还是 5。

我们需要做的是通过引用来传递变量,这样它才会递增,因为我真正想做的是影响这个变量,那么我们该怎么做呢,如何通过将这个变量传递到函数中来修改它呢?

上期我们讨论了指针,还记得指针就是我们的内存地址吧,从理论上讲,我们可以做的是,可以没有将实际值 5 传递给函数,但是可以把 a 变量的内存地址传递进去,因为我们可以在这个函数中做的是可以查找那个内存地址,然后修改那个内存地址中的值。因为我们已经将该内存地址传递给了函数, 所以我们理论上是可以这样做的,所以需要怎么修改呢?采用指针。

[igNvYz.png

在调用函数 Increment 时我传入的是 a 的内存地址,而不仅仅是值 5;我做的另外一件事就是 逆向引用 value,这样我们就可以直接将值写入这个内存,而不是修改指针本身,如果我们在 value++ 之前不加 *,没有 dereference 操作符,那么它就会递增这个内存地址,而不是实际值。还有就是你会看到我在逆向引用后加了括号,因为优先级的关系,如果不加括号,它会先做 value++ 增量运算,然后再做逆向引用,但我们想做的刚好相反,是先做逆向引用,然后是增量运算。

如果我们编译代码,你会看到打印出了 6。我们成功地将变量传递到一个函数中。

本期是关于引用的,所以我们要用更加简单、更少的代码、更少的修饰语法来实现上面的过程。

简洁的引用

我会用一个引用来解决问题。

[igNJww.png

我重写了这个函数,使用引用代替指针,这样我们就不需要逆向引用了,然后我们就不要传递 a 的内存地址,只需要传递 a 即可,它是通过引用传递的。运行之后,效果和之前是完全一样的,不过这次的代码明显比之前的更漂亮,其实这也是唯一的区别了。

好了,这就是引用的全部了,它们只是语法糖,对于引用没有什么是指针不能做的,指针就像引用,不过它更有用,也更强大。然而,你可以使用引用的时候,就一定要用引用,因为它会让你代码更加简洁和简单,引用使得你的代码干净得多。

关于引用,我想提到的另一件重要的事情是, 一旦你声明了一个引用,你不能改变它引用的东西。

举个例子。

[igNKxa.png

编译当然可以通过,不过可不是你想的那个意思。它仅仅是把 a 的值变为了 b 的值,也就是 8。

这意味着如果你引用一个变量时,你需要把他赋值,你不能不赋值,编译器不会让你这么做的。你可以试一下。

当你声明一个引用时,必须马上给它赋值,因为他必须引用一些东西,时刻牢记它不是一个真正的变量,只是一个引用。

在这个例子中。如果我真的需要实现这种功能,——想改变引用的值,我该怎么做呢?

可以这样做

好吧,也有办法可以实现。

[igNLMx.png

首先它这不是一个真正的变量,我们需要先创建变量,然后设置它来指向 a,然后,我们更改为指向 b,当然,我老是说 “指向” 这个词,我们说的其实是指针,所以改一下,让我们把它作为一个指针,我们一开始可以把它设为 a 的内存地址,当我把指向变成了 b 时,我们需要 dereference (逆向引用)这个指针,然后给它赋值,在这个例子中我让 a 等于 2,b 等于 1,打印出来应该是 2 和 1,运行之后,你可以看到结果是对的。

后话

这就是我想说的关于引用的内容了,非常简单的东西,我们在未来会使用更多的引用操作,你以后会一直用它,像指针一样。随着这个系列的深入你会看到更多的例子。

本期就是这样,下期再见。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL索引数据结构入门

之前松哥写过一个 MySQL 系列,但是当时是基于 MySQL5.7 的,最近有空在看 MySQL8 的文档,发现和 MySQL5.7 相比还是有不少变化,同时 MySQL 又是小伙伴们在面试时一个非常重要的知识点,因此松哥打算最近再抽空和小伙伴们…

Golang数据类型比较

直接使用比较的情况 分类说明是否能比较说明基本类型整型( int/uint/int8/uint8/int16/uint16/int32/uint32/int64/uint64/byte/rune等)浮点数( float32/float64)复数类型( complex64/complex128)字符串&a…

Linux查看端口

目录 1.查看已知端口的使用情况 2.查看所有端口的占用情况 3.查看占用端口的程序的进程号 4.杀死进程号 1.查看已知端口的使用情况 #例:8080 可使用命令: netstat -anp | grep 8080 结果如下: 还可以使用这条命令: netstat -tln | grep 8080 结果如下: 区别:第一条命令后面显示…

NumPy 秘籍中文第二版:十二、使用 NumPy 进行探索性和预测性数据分析

原文:NumPy Cookbook - Second Edition 协议:CC BY-NC-SA 4.0 译者:飞龙 在本章中,我们涵盖以下秘籍: 探索气压探索日常气压范围研究年度气压平均值分析最大可见度用自回归模型预测气压使用移动平均模型预测气压研究年…

爱智EdgerOS之深入解析离线下载任务

一、需求分析 在日常使用计算机的过程中,看到喜欢的资源不可避免地想把它下载到我们的设备上保存下来,比如图片,音视频资源,文档资源等,基于这种应用场景,现在来看看在爱智设备上可以如何实现呢&#xff1…

76-TCP协议,UDP协议以及区别

TCP协议,UDP协议,SCTP协议一.TCP协议1.什么是TCP协议2.TCP协议的特点3.TCP头部结构4.TCP状态转移5.TCP超时重传二.UDP协议1.什么是UDP协议2.UDP协议的特点三.TCP和UDP的区别一.TCP协议 1.什么是TCP协议 TCP(Transmission Control Protocol)协议即为传输控制协议,是一种面向连…

2023-04-12 面试中常见的数组题目

数组中的问题其实最常见 通过基础问题,掌握写出正确算法的“秘诀”巧妙使用双索引技术,解决复杂问题对撞指针- 滑动窗口 1 从二分查找法看如何写出正确的程序 本节学习重点:处理边界问题! 1.确定边界范围方法,先用区…

微服务架构-服务网关(Gateway)-权限认证(分布式session替代方案)

权限认证-分布式session替代方案 前面我们了解了Gateway组件的过滤器,这一节我们就探讨一下Gateway在分布式环境中的一个具体用例-用户鉴权。 1、传统单应用的用户鉴权 从我们开始学JavaEE的时候,就被洗脑式灌输了一种权限验证的标准做法,…

Elasticsearch:集群管理的一些建议

在之前的文章 “Elasticsearch:集群管理” ,我们对集群管理做了一些介绍。在今天的文章中,我们接着来聊一下有关配置的方面的问题。这在很大程度上取决于你的用例,是索引还是搜索繁重。 我们将在这里讨论在集群设置方面我们需要关…

Leetcode.130 被围绕的区域

题目链接 Leetcode.130 被围绕的区域 mid 题目描述 给你一个 m x n的矩阵 board,由若干字符 X和 O,找到所有被 X围绕的区域,并将这些区域里所有的 O用 X填充。 示例 1: 输入:board [[“X”,“X”,“X”,“X”],[“X…

「Cpolar」使用Typecho搭建个人博客网站【内网穿透实现公网访问】

💂作者简介: THUNDER王,一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学本科在读,同时任汉硕云(广东)科技有限公司ABAP开发顾问。在学习工作中,我通常使用偏后端的开发语言A…

在 Python 中计算两个数字之间的百分比

要计算两个数字之间的百分比,请将一个数字除以另一个数字,然后将结果乘以 100,例如 (30 / 75) * 100。这显示第一个数字占第二个数字的百分比。 在示例中,30 是 75 的 40%。 def is_what_percent_of(num_a, num_b):return (num_a…

基于SVG的HMI组件

人机界面是自动化领域不可或缺重要组成部分。人机界面系统的设计看上去并没有太大的技术门槛,但是设计一个HMI系统的工作量是巨大的,如果你没有足够的耐心和精力是难以完成一个通用HMI系统的。构建UI控件库就是一个似乎永远完不成的事情,用户…

Halo博客建站实战以及问题汇总

目录 简介 特性 快速开始 安装步骤 环境准备 Docker-compose方式部署 问题汇总 mac端无法访问页面 页面登录提示账号密码错误 重装注意点 资料 官方文档 简介 Halo 强大易用的开源建站工具 特性 代码开源 我们的所有代码开源在 GitHub 上且处于积极维护状态&…

《分解因数》:质因数分解

目录 一、题目&#xff1a; 二、思路&#xff1a; 三、代码&#xff1a; 一、题目&#xff1a; 分解因数 《分解因数》题目链接 所谓因子分解&#xff0c;就是把给定的正整数a&#xff0c;分解成若干个素数的乘积&#xff0c;即 a a1 a2 a3 ... an,并且 1 < a1…

HCIA第二次笔记

目录 OSI/RM七层参考模型——开放式的系统互联参考模型 核心——分层 TCP/IP模型——TCP/IP协议簇 应用层 应用层协议 封装与解封装 传输层 TCP协议和UDP协议的区别 TCP的报文 TCP的三次握手 TCP的四次挥手 TCP的四种可靠传输机制 OSI/RM七层参考模型——开放式的系…

[目标识别-论文笔记]Object Detection in Videos by Short and Long Range Object Linking

文章标题&#xff1a;2018_Cite13_Tang——Object Detection in Videos by Short and Long Range Object Linking 这篇论文也被叫做“2019_Cite91_TPAMI_Tang——Object Detection in Videos by High Quality Object Linking” 如果这篇博客对你有帮助&#xff0c;希望你 点赞…

学生信息管理系统【GUI/Swing+MySQL】(Java课设)

系统类型 Swing窗口类型Mysql数据库存储数据 使用范围 适合作为Java课设&#xff01;&#xff01;&#xff01; 部署环境 jdk1.8Mysql8.0Idea或eclipsejdbc 运行效果 本系统源码地址&#xff1a;https://download.csdn.net/download/qq_50954361/87673902 更多系统资源库…

【设计模式】如何在业务开发中使用适配器模式?

文章目录前言适配器模式定义通用代码实现适用场景案例场景分析一坨坨代码实现适配器模式重构总结前言 适配器模式&#xff08;Adapter Pattern&#xff09;&#xff1a;将一个类的接口变换成客户端所期待的另一种接口&#xff0c;从而使原本因接口不匹配而无法在一起工作的两个…

高速Serdes技术(FPGA领域应用)

目录引入一、Serdes&#xff08;概念-历程&#xff09;1、概念2、技术现状3、发展历程二、Serdes结构三、在FPGA领域中的运用四、Serdes跟Lvds的关系五、Xilinx 有关 serdes的文档六、参考文献引入 回顾接口技术发展历史&#xff0c;其实数据的传输最开始是低速的串行接口&…