当前位置: 首页 > news >正文

【C++初阶】:C++入门,引用概念及其性质

文章目录

      • 一、引用的概念
      • 二、引用的语法规则
        • 1、引用特性
        • 2、常引用
      • 二、引用的使用场景
        • 1. 引用做参数
        • 2. 引用做返回值
      • 三、引用和指针的区别

在这里插入图片描述

一、引用的概念

首先明确一下,引用不是定义一个新的变量,而是给已经存在的变量起一个别名,变量和他的引用是共用同一块内存空间。

C++中的引用就是和人的外号一样,人的本名和外号都是指同一个人。比如:李逵,在家称为"铁牛",江湖上人称"黑旋风"。

二、引用的语法规则

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

#include<iostream>
using namespace std;int main()
{int a = 10;int& b = a;  // b是a的引用cout << a << endl;cout << b << endl;return 0;
}

在这里插入图片描述
变量a 和它的引用b使用的是同一块内存空间

int main()
{int a = 10;int& b = a;cout << &a << endl;cout << &b << endl;  // a 和 b 使用的是同一块内存空间return 0;
}

在这里插入图片描述

int main()
{int a = 10;int& b = a;b = 20; cout << a << " " << b << endl;return 0;
}

在这里插入图片描述由于变量和变量的引用是使用的同一块内存地址,这意味着如果改变b,那么a也会随着b的改变而改变。

1、引用特性

1、引用在定义时必须初始化

void testref()
{int a = 10;int& b;  // err 引用是必须初始化
}

在这里插入图片描述

2、一个变量可以有多个引用
一个变量被引用后,可以继续被引用,也可以引用变量的引用。

void testref02()
{int a = 10;int& b = a;int& c = a;  // 一个变量可以有多个引用 int& d = b;  // 可以引用变量的引用
}

3、引用一旦引用一个实体(变量),就不能在引用其他实体

void testref02()
{int a = 10;int b = 20;int& c = a;int& c = b;  // c不可以重复引用
}

在这里插入图片描述
这里要和C/C++中的指针区分一下,指针可以改变指针指向的对象,但是引用不可以。

2、常引用

一般来说,引用只可以引用变量,不可以直接引用常量的。因为常量是不可以改变的。

void testref03()
{int& a = 10;  // err, 不可以引用常量
}

在这里插入图片描述
解决办法
想要引用常量的话,只要在引用的前面加一句const,加上const之后,引用就不可以发生改变。
除了上述情况,引用的类型不同也会导致编译不同过,这是因为在发生类型转化的过程中,会产生临时变量,而临时变量具有常性,和常量一样,需要用const引用。

在这里插入图片描述

void testref04()
{char ch = 'a';int& a = ch;  // 不可以引用不同类型的变量,类型转化时会产生临时变量,临时变量具有常性
}

在这里插入图片描述

产生临时变量时都要用常引用。

void testref05()
{char ch = 'a';const int& a = ch;
}

二、引用的使用场景

1. 引用做参数

在C语言学习指针的时候一定学过一个交换函数Swap,那时候我们在Swap时参数必须要用传址调用,因为如果用传值调用的话,形参的改变是不影响实参的,无法实现交换功能。
在这里插入图片描述

但是如果我们学了引用的话就不需要使用传址调用了,可以直接用引用作为参数,引用的形参就是实参的别名

void func(int& x, int& y)
{cout << &x << endl;cout << &y << endl;
}int main()
{int a = 10;int b = 20;cout << &a << endl;cout << &b << endl;cout << "-------------" << endl;func(a, b);return 0;
}

在这里插入图片描述
用引用的话,在函数传参时就不需要传址调用了,更加方便。

void Swap(int& a, int& b)
{int tmp = a;a = b;b = tmp;
}
2. 引用做返回值

是的,你没看错,引用不仅可以做函数的参数,还可以做函数的返回值,我们之前写的具有返回值的函数返回的并不是直接将函数中的变量,而是返回的变量的一份临时拷贝,而拷贝是需要付出一定代价的,这样会降低我们代码的效率,但是如果我们用引用返回的话就可以避免拷贝的代价,在对程序性能要求高且允许使用引用的情况下,尽量使用引用返回。

注意:并不是所有的函数都可以用引用返回,有些强行使用引用返回会造成一些不必要的错误。
函数可以用引用返回的条件:
函数的返回值在出函数作用域后不会被销毁。

int& Count()
{static int n = 0;n++;// ... return n;
}

静态变量出了函数定义域之后不会销毁,可以用引用返回。

int& Count()
{int n = 0;n++;// ...return n;  // n在出函数作用域后就销毁了,不要用引用返回
}

传值、传引用的的效率比较
用值作为参数或返回值时,在传参和返回期间,函数是不会直接传递实参或则是将变量之间返回,而是传递实参或者返回变量的一份临时拷贝,所以用值传参或者做返回值效率是非常低的,尤其是当参数或者返回值类型非常大时,效率更加低下。

值和引用作为函数参数的效率对比:

#include <time.h>
// 传值
struct A{ int a[10000]; }; 
void TestFunc1(A a) {}
// 传引用
void TestFunc2(A& a) {}void TestRefAndValue()
{A a;// 以值作为函数参数size_t begin1 = clock();for (size_t i = 0; i < 10000; i++){TestFunc1(a);}size_t end1 = clock();// 以引用作为函数参数size_t begin2 = clock();for (size_t i = 0; i < 10000; i++){TestFunc2(a);}size_t end2 = clock();// 分别计算两个函数运行结束后的时间cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
}

在这里插入图片描述
传值的效率明显低于传引用。

值和引用作为函数返回值的效率对比:

#include<time.h>
struct A { int a[10000]; };A a;
// 值返回
A TestFunc1() { return a; }
// 引用返回
A& TestFunc2() { return a; }void TestReturnByRefOrValue()
{// 以值作为函数的返回值类型size_t begin1 = clock();for (int i = 0; i < 100000; i++)TestFunc1();size_t end1 = clock();// 以引用作为函数的返回值类型size_t begin2 = clock();for (int i = 0; i < 100000; i++)TestFunc2();size_t end2 = clock();// 计算两个函数运算完成之后的时间cout << "TestFunc1() Time:" << begin1 - end1 << endl;cout << "TestFunc2() Time:" << begin2 - end2 << endl;
}int main()
{TestReturnByRefOrValue();return 0;
}

在这里插入图片描述
传值和指针在作为传参以及返回值类型上效率相差很大。

三、引用和指针的区别

1、语义概念上引用就是变量的别名,没有独立空间,和引用实体共用同一块空间。

int main()
{int a = 10;int& b = a;cout << &a << endl;cout << &b << endl;return 0;
}

在这里插入图片描述
底层实现上实际是有空间的,因为引用是按照指针方式来实现的。

在这里插入图片描述
2、引用必须初始化,指针可以在定义时不初始化

int a = 20;
int* pa;  // 指针可以不初始化
int& ra;  // 引用必须初始化

在这里插入图片描述

3、 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体

4、没有NULL引用,但有NULL指针。

int* pa = NULL;
int& ra = NULL;  // err,没有NULL引用

在这里插入图片描述
5、在sizeof中含义不同引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)

#include<string>
int main()
{string str = "abcdef";string& rstr = str;string* pstr = &str;cout << "string& rstr = str: " << sizeof(rstr) << endl;cout << "string* pstr = &str: " << sizeof(pstr) << endl;return 0;
}

在这里插入图片描述
6、 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小

int main()
{int a = 10;int& ra = a;int* pa = &a;ra++;pa++;cout << "int& ra = a:  " << ra << endl;cout << "int* pa = &a: " << pa << endl;return 0;
}

在这里插入图片描述
7、有多级指针,但是没有多级引用

int a = 10;
int* pa = &a;
int** ppa = &pa;
int& ra = a;
int&& rra = ra;  // 无多级引用

在这里插入图片描述
8、访问实体方式不同,指针需要显式解引用,引用编译器自己处理

int main()
{int a = 10;int* pa = &a;int& ra = a;cout << ra << endl;cout << *pa << endl;return 0;
}

在这里插入图片描述
9、引用比指针使用起来相对更安全,毕竟指针存在野指针,而不存在野引用。

相关文章:

【C++初阶】:C++入门,引用概念及其性质

文章目录 一、引用的概念二、引用的语法规则1、引用特性2、常引用 二、引用的使用场景1. 引用做参数2. 引用做返回值 三、引用和指针的区别 一、引用的概念 首先明确一下&#xff0c;引用不是定义一个新的变量&#xff0c;而是给已经存在的变量起一个别名&#xff0c;变量和他…...

Linux 中的 crontab 命令介绍以及使用

文章目录 Linux Crontab 完全指南什么是 Crontab&#xff1f;Crontab 文件的基本格式特殊符号解释&#xff1a; 如何使用 Crontab查看当前用户的 Crontab编辑 Crontab删除 Crontab Crontab 示例每天晚上 12 点备份数据库每个工作日的早上 9 点发送日报每隔 15 分钟清理临时文件…...

单片机组成原理

大纲 C语言指针如何与硬件对应 底层疑问的源头 我已造好轮子&#xff0c;等你来理解 外设电路大概是什么结构 解决底层开发中关于配置、寄存器) 外设电路的疑问 从此可以快速上手新的单片机、新的外设芯片 对外设芯片的内部结构有本质理解&#xff0c;看手册不再是问题 固件库…...

《机器学习》—— SVD奇异值分解方法对图像进行压缩

文章目录 一、SVD奇异值分解简单介绍二、代码实现—SVD奇异值分解方法对图像进行压缩 一、SVD奇异值分解简单介绍 SVD&#xff08;奇异值分解&#xff09;是一种在信号处理、统计学、线性代数、机器学习等多个领域广泛应用的矩阵分解方法。它将任何 mn 矩阵 A 分解为三个特定矩…...

英文文本预处理——文本清理

文本清理定义 文本清理是英文文本预处理的重要步骤,旨在提高数据质量和一致性。以下是文本清理的具体内容: 去除标点符号 (Removing Punctuation): 删除文本中的标点符号,如句号、逗号、问号等。这一步骤有助于减少文本噪音,使得文本分析更加专注于有意义的词汇内容。 去…...

Spring Boot 注解探秘:常用配置值读取注解的魔力

在 Spring Boot 应用开发中&#xff0c;我们会常常借助Apollo&#xff0c;Spring Cloud Config等配置中心来集中管理配置信息&#xff0c;在拥有配置信息之后&#xff0c;高效且准确地读取这些配置信息无疑是极为关键的一环。今天我们就来介绍几个常用的用于配置值读取的注解。…...

Ps初步使用教程

1.画面快捷键 Ctrl鼠标滚轮&#xff1a;画面左右移动 Shift鼠标滚轮&#xff1a;画面上下快速移动&#xff08;不加Shift正常速度移动&#xff09; Alt鼠标滚轮&#xff1a;画面大小缩放 2.工具快捷键 ShiftG&#xff1a;渐变、油漆桶、3D材质施放 切换 CtrlO&#xff1a…...

远程连接Hiveserver2服务

目录 1.修改 core-site.xml 和 hive-site.xml 的配置文件 2.启动HiveServer2服务 3.启动Beeline工具连接Hiveserver2服务 4.利用IDEA工具连接Hiveserver2服务 完成Hive本地模式安装后&#xff0c;可以启动hiveserver2服务进行远程连接和操作Hive。 1.修改 core-site.xml …...

PDF样本图册转换为一个链接,随时打开无需印刷

想象一下&#xff0c;您手中有一本厚重的样本图册&#xff0c;里面包含了丰富多样的内容&#xff0c;如产品介绍、项目方案、学术论文等。在过去&#xff0c;您需要逐一翻阅、筛选&#xff0c;甚至为了便于查看&#xff0c;不得不将其印刷出来。如今&#xff0c;借助先进的数字…...

自己动手实现mybatis的底层框架(不用动态代理直接用执行器、用动态代理自己实现。图文分析!)

目录 一.原生mybits框架图分析 自己实现Mybatis框架的分析 两种框架操作数据库的方法&#xff1a; 二.搭建开发环境 1.先创建一个maven项目 2.加入依赖(mysql dom4j junit lombok) 三.mybatis框架的设计思路 具体实现过程 3.1实现任务阶段 1- 完成读取配置文件&#x…...

项目日志——日志落地模块的设计、实现、测试

文章目录 日志落地模块设计实现扩展实现测试 日志落地模块 设计 功能是&#xff0c;将格式化完成后的日志消息字符串&#xff0c;输出到指定的位置 支持将日志落地到不同的位置 标准输出指定文件滚动文件 滚动文件按照时间或者大小进行滚动切换&#xff0c;可以按照天数对…...

CTK框架(七):事件监听

目录 1.概述 2.监听接口 3.具体实现 1.概述 CTK&#xff08;Common Toolkit&#xff09;框架中的事件监听机制是一个重要的功能&#xff0c;它允许开发者在特定事件发生时接收到通知并执行相应的操作。CTK框架主要支持三种类型的事件监听&#xff1a;框架事件、插件事件和服…...

一区霜冰算法+双向深度学习模型+注意力机制!RIME-BiTCN-BiGRU-Attention

一区霜冰算法双向深度学习模型注意力机制&#xff01;RIME-BiTCN-BiGRU-Attention 目录 一区霜冰算法双向深度学习模型注意力机制&#xff01;RIME-BiTCN-BiGRU-Attention效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现RIME-BiTCN-BiGRU-Attention霜冰算法…...

C语言 | Leetcode C语言题解之第396题旋转函数

题目&#xff1a; 题解&#xff1a; #define MAX(a, b) ((a) > (b) ? (a) : (b))int maxRotateFunction(int* nums, int numsSize){int f 0, numSum 0;for (int i 0; i < numsSize; i) {f i * nums[i];numSum nums[i];}int res f;for (int i numsSize - 1; i &g…...

利士策分享,克服生活中的困难:走好勇攀高峰的每一步

利士策分享&#xff0c;克服生活中的困难&#xff1a;走好勇攀高峰的每一步 在这个纷繁复杂的世界里&#xff0c;每个人都是自己生命旅程中的行者&#xff0c;而生活&#xff0c;则是一条既铺满鲜花又布满荆棘的道路。 我们或许会在某个清晨醒来&#xff0c;发现自己正站在一座…...

PurchasereturnController

目录 1、 PurchasereturnController 1.1、 反审核退货单 1.1.1、 //配件ID 1.1.2、 //配件编码 1.1.3、 //修改后仓库 1.1.4、 //修改配件信息表库存量 PurchasereturnController using QXQPS.Models; using QXQPS.Vo; using System; using System.Collection…...

mysql 学习笔记 八

总结 自动提交 查看自动提交状态&#xff1a;SELECT AUTOCOMMIT &#xff1b; 设置自动提交状态&#xff1a;SET AUTOCOMMIT 0 。 手动提交 AUTOCOMMIT 0 时&#xff0c;使用 COMMIT 命令提交事务。 事务回滚 AUTOCOMMIT 0 时&#xff0c;使用 ROLLBACK 命令回滚事务。 …...

反序列化漏洞练习2

拿到题目&#xff0c;发现目标是获得flag.php的内容,且sis中admin和passwd等于sis2407时会输出fag的内容 根据源码编写序列化代码 <?php error_reporting(0); class sis{public $admin;public $passwd;public function __construct(){$this->admin "sis2407"…...

基于SpringBoot的社区医院管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 基于JavaSpringBootVueMySQL的社团管理系统【附源码文档】、…...

YOLOv8安装配置教程(Windows版)

YOLOv8安装配置教程&#xff08;Windows版&#xff09; 简介&#xff1a;最近由于选择了人工智能方向的专业选修课&#xff0c;课程需要安装配置YOLOv8&#xff0c;经过查阅各种资料后才发现&#xff0c;许多教程都比较老旧&#xff0c;并且文件位置也发生了变化&#xff0c;所…...

Spring Boot 实现流式响应(兼容 2.7.x)

在实际开发中&#xff0c;我们可能会遇到一些流式数据处理的场景&#xff0c;比如接收来自上游接口的 Server-Sent Events&#xff08;SSE&#xff09; 或 流式 JSON 内容&#xff0c;并将其原样中转给前端页面或客户端。这种情况下&#xff0c;传统的 RestTemplate 缓存机制会…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

uniapp手机号一键登录保姆级教程(包含前端和后端)

目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号&#xff08;第三种&#xff09;后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分&#xff1a; 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...

数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !

我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...

篇章二 论坛系统——系统设计

目录 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 1. 数据库设计 1.1 数据库名: forum db 1.2 表的设计 1.3 编写SQL 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 通过需求分析获得概念类并结合业务实现过程中的技术需要&#x…...

rm视觉学习1-自瞄部分

首先先感谢中南大学的开源&#xff0c;提供了很全面的思路&#xff0c;减少了很多基础性的开发研究 我看的阅读的是中南大学FYT战队开源视觉代码 链接&#xff1a;https://github.com/CSU-FYT-Vision/FYT2024_vision.git 1.框架&#xff1a; 代码框架结构&#xff1a;readme有…...