C++练级之初级:第四篇

news2024/11/13 11:08:49

C++练级之初级:第四篇

引用

  • C++练级之初级:第四篇
    • 1.引用
      • 1.1引用的介绍
      • 1.2引用的使用场景
      • 1.3常引用
    • 2.引用的底层
    • 3.引用的与指针的比较
  • 总结

1.引用

1.1引用的介绍

🤔首先还是一个问题,引用是解决C语言什么不足?

在这里插入图片描述
指针在,这里传参和访问变量有点麻烦, 能不能简单一点? 于是C++的大佬就发明了一种简单的语法:引用;

🤔🤔什么是引用?

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间

在这里插入图片描述
就像李逵的外号叫“黑旋风”,“铁牛”,“李鬼”等等,他们都是一个人,对别名操作就是对其本身操作;

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

🤔🤔🤔那么我们在用引用的时候有什么问题要注意的吗?

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


总结:

  • 引用是对某个实体起别名,操作的是同一块空间
  • 引用类型必须和引用实体是同种类型的;
  • 引用在定义时必须初始化
  • 一个变量可以有多个引用
  • 引用一旦引用一个实体,再不能引用其他实体,即对这个实体一直引用到最后;

注意: 这里不要和java搞混:java中的引用是可以改变指向的,C++中的引用是改变不了的,即一直是一个实体的别名;


1.2引用的使用场景

🤔既然了解了什么是引用,那么引用一般都用在什么地方呢?

  1. 引用做参数(输出型参数)

注解: 🤔🤔什么是输出型参数?
输出型参数:形参的改变影响实参;
输入型参数:形参的改变不影响实参;

在这里插入图片描述
在C语言中我们要实现这种输出型参数就一定要用指针,但是指针书写太麻烦,于是在C++中我们可以用引用类型作为形参来实现输出型参数;


1.1 引用做参数,可以提高效率(大对象/深拷贝类对象)

#include<iostream>
#include <time.h>
using namespace std;
struct A 
{ 
	int a[10000]; //40000byte
};
void TestFunc1(struct A a)
{

}
void TestFunc2(struct A& a)
{

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

在这里插入图片描述

🤔🤔为什么在大对象或者深拷贝类对象,引用或者指针比传值调用的效率更高?

我们知道形参是对实参的一份临时拷贝,那么对于大对象而言,比如40000byte的数组,那么形参就会开销拷贝所用的时间,效率肯定要比传引用或者指针来的慢,因为传引用只需传别名,指针也只要传一个指针变量指向这块空间;


  1. 引用做返回值(提高效率),返回后可以对返回值进行修改
#include<iostream>
#include <time.h>
using namespace std;
struct A 
{ 
	int a[10000]; 
};
struct A a;
struct A TestFunc1()
{
	return a;
}
struct A& TestFunc2()
{
	return a;
}
void TestRefAndValue()
{
	// 以值作为的返回值类型
	size_t begin1 = clock();
	for (size_t i = 0; i < 10000; ++i)
		TestFunc1();
	size_t end1 = clock();
	// 以引用作为的返回值类型
	size_t begin2 = clock();
	for (size_t i = 0; i < 10000; ++i)
		TestFunc2();
	size_t end2 = clock();
	// 分别计算两个函数运行结束后的时间
	cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;
	cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
}

int main()
{
	TestRefAndValue();
	return 0;
}

在这里插入图片描述

🤔🤔为什么在传大对象或者深拷贝类对象时,值返回的效率比引用返回的效率低?

注意:编译器是根据返回值类型来判断是否为值返回,若是值返回则都需要创建临时变量,临时变量可以是寄存器(返回的对象较小)

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

因为值返回需要创建临时变量,而引用返回不需要创建临时变量,直接返回别名,所以在返回大对象时,引用返回的效率比值返回的效率高


🤔🤔🤔那么我们在引用返回时有什么注意点吗?

👇这两段代码有什么区别?

在这里插入图片描述

在这里插入图片描述

😁进入正题:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

🤔🤔🤔这是为什么?

在这里插入图片描述

这个与这段代码类似:
在这里插入图片描述

解析:这里的ret接收到了n的地址,但是n这块空间被销毁了,只是vs并没有清理栈帧中的数据,所以通过n的地址可以访问到n,但这是侥幸访问的,因为右边的图可以看出,我们调用其他函数时,其他函数创建栈帧时就会覆盖那个栈帧的数据(覆盖),所以通过n的地址访问就是随机值,这种问题一般称为野指针的访问;


上面的问题类似(ret2访问的是一个销毁的变量)

  • 如果test2函数结束,函数栈帧销毁(使用权还给操作系统),没彻底清理栈帧,那么ret2的结果侥幸是正确的;
  • 如果test2函数结束,函数栈帧销毁(使用权还给操作系统),彻底清理栈帧,那么ret2的结果随机的;
    在这里插入图片描述
    总而言之,函数返回值为引用类型时,在vs中,函数栈帧销毁后(还给操作系统),函数栈帧不会清理(变成0xcccccccc),所以用值来接收是侥幸正确的,因为是简单的赋值操作,但在其他编译器中可能是错的(函数栈帧销毁后直接清理),那么用值来接收就会是随机值,在vs中如果用引用来接收更不推荐,因为下面一旦调用了其他函数,其他函数的栈帧就会覆盖上去,那么引用就会是随机值

总结引用的引用场景

1.基本上所有情况下都有可以用引用类型传参;
2.谨慎用引用类型做函数的返回值,除了对象出了函数作用域还在的情况下可以用;

下面就举几个正确的使用引用做函数返回值的正确应用:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.3常引用

🤔常引用是什么?
引用的对象不能改变的引用,一般写法:在引用类型前加const,注意:常引用是不能改变的

错误的引用:
在这里插入图片描述
正确的引用:
在这里插入图片描述
在这里插入图片描述


🤔🤔这段代码是什么意思呢?

在这里插入图片描述
从上面的引用的注意点我们知道引用的类型必须相同,所以报错;

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

所以当两个类型不同时,但是你一定要放进去就会发生类型转换,发生类型转化的时候会创建一个临时变量,这个临时变量存放的是一个转换过后的值(常性),所以要用常引用;

常性和常量是不同的
常性:const修饰的变量,本质是变量,具有长属性(不可改变);
常量:本质是常量,不可改变;

🤔🤔为什么运算符两边的数据类型不一致时要产生临时变量?

在这里插入图片描述

因为我们不能改变 i 本身的值,如果不建立临时变量直接进行类型转换的话,i的值就会变;

在这里插入图片描述

在这里插入图片描述


🤔🤔🤔那如果我就直接在正确的引用前加上const会发生什么?

在这里插入图片描述
在这里插入图片描述
那我们对a++,b++,c会不会变呢?

在这里插入图片描述

总而言之,就是如果在正确的引用前加上const,会导致加上const这个引用的权限缩小(不能改变a),但是本质上还是同一块空间,只不过加上const的那个引用改不了;

2.引用的底层

🤔引用的底层是什么?(现在先简单了解一下)

在这里插入图片描述

在这里插入图片描述


汇编层面:

在这里插入图片描述
底层上引用还是要开空间的
对a进行取别名本质上就是把a的地址给ra


注意:但是在写代码时我们要遵循语法,还是要认为引用没开空间;


3.引用的与指针的比较

🤔那么引用和指针有什么不同呢?

引用和指针的不同点:

  1. 引用概念上定义一个变量的别名,指针存储一个变量地址
  2. 引用在定义时必须初始化,指针没有要求;
  3. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体;
  4. 没有NULL引用,但有NULL指针
  5. sizeof中含义不同引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节);
  6. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
  7. 有多级指针,但是没有多级引用
  8. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理;
  9. 引用比指针使用起来相对更安全(指针有空指针问题引用却没有这个问题)

在这里插入图片描述

总结

今天主要学习了什么是引用,引用的场景,引用的底层,引用和值得比较,引用和指针的比较,引用做返回值时的注意点,常引用等,如果喜欢本篇不妨留下一个❤️❤️❤️,下篇见!

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python自动化sql注入:布尔盲注

在sql注入时&#xff0c;使用python脚本可以大大提高注入效率&#xff0c;这里演示一下编写python脚本实现布尔盲注的基本流程&#xff1a; 演示靶场&#xff1a;sqli-labs 布尔盲注 特点&#xff1a;没有回显没有报错&#xff0c;但根据sql语句正常与否返回不同结果&#x…

新手做电商直播带货怎么和快递合作谈价格

新手做电商直播带货怎么和快递合作谈价格达人带货一般怎样的合作模式&#xff1f;#达人带货 #直播带货 #红人 #百收网 跟快递谈价其实是有方法的&#xff0c;快递的价格不是说不能打下来&#xff0c;就是需要你们多一点点的心机。这个视频我就再给你们补充三个方法&#xff0c;…

HCIP之STP

企业网三层架构 线路冗余—二层网络桥接环路 因为路由器的路由表是由相对完善的计算所得&#xff0c;且存在防环规则&#xff1b;故路由器物理链路上实施备份时&#xff0c;一般不会出现环路&#xff1b;但交换转发数据依赖MAC表&#xff08;CAM表&#xff09;&#xff0c;该表…

【模式识别4】YOLO目标检测数据集xml格式转txt格式

YOLO目标检测数据集xml格式转txt格式 1. 转换前的xml格式2. xml格式转txt格式代码2.1 源代码2.2 需要修改的地方 3. 转换后的txt格式 代码资源&#xff1a;voc2txt.py 1. 转换前的xml格式 如果我们使用LabelImg工具标注数据集&#xff0c;生成的xml文件如下&#xff1a; xml…

Linux运维:推荐八款Linux远程连接工具

目录 2、XShell 3、SecureCRT 4、PuTTY 5、WindTerm 6、iTerm2 7、MobaXterm 8、Termius 今天给大家推荐八款Linux远程连接工具&#xff0c;非常实用&#xff0c;希望对大家能有所帮助&#xff01; 1、NxShell NxShell是一款开源的Linux远程管理工具&#xff0c;是我日…

Spring Boot 接口加解密

1. 介绍 在我们日常的Java开发中&#xff0c;免不了和其他系统的业务交互&#xff0c;或者微服务之间的接口调用 如果我们想保证数据传输的安全&#xff0c;对接口出参加密&#xff0c;入参解密。 但是不想写重复代码&#xff0c;我们可以提供一个通用starter&#xff0c;提…

【python数据可视化】基于networkx的10个绘图技巧

一、说明 networkx在02年5月产生&#xff0c;是用python语言编写的软件包&#xff0c;便于用户对复杂网络进行创建、操作和学习。利用networkx可以以标准化和非标准化的数据格式存储网络、生成多种随机网络和经典网络、分析网络结构、建立网络模型、设计新的网络算法、进行网络…

解决java.lang.IllegalStateException: Failed to load ApplicationContext错误~

错误描述&#xff1a; Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component class: file [D:\SSM\SSM_3.22\spring_transaction\target\classes\spring_txAnnotation\Controller\BookController.class]; nested …

装饰器模式C++用法示例

六.装饰器模式 一.装饰器模式1.原理2.适用场景 二.C程序示例1.语法组成2.C示例 一.装饰器模式 1.原理 装饰器模式是一种结构性设计模式&#xff0c;其目的是通过包装对象来扩展其行为而不改变其接口。该模式可以动态地将责任附加到对象上&#xff0c;从而提供一种灵活的替代方…

SQL Server基础 第三章 数据表基本操作(增删改查,不允许保存更改异常!)

往表里插数据我们现在有两种方式第一种是编辑直接修改&#xff0c;第二种是通过查询来修改数据 两种方法的区别 第一种更直接&#xff0c;如果数据量小那么直接改就好了&#xff0c;那如果数据量稍微庞大我们就需要用新建查询来进行表内容的修改了&#xff01;&#xff01;&a…

【Linux】进程信号 --- 信号的产生 保存 捕捉递达

被爱情困住的是傻子 文章目录 一、信号的预备知识1.通过生活例子来理解信号2.迁移到进程上来理解信号 二、信号的发送&#xff08;修改PCB的信号位图&#xff09;1.通过键盘发送信号&#xff08;kill指令 和 热键&#xff09;2.通过系统调用发送信号&#xff08;kill系统调用 和…

前端技术的miniui 和bootstartp

前端技术的miniui 和bootstartp 目录概述需求&#xff1a; 设计思路实现思路分析1.前端技术boostatrp2.miniui: 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better re…

1686_MATLAB处理Excel文件

全部学习汇总&#xff1a; GreyZhang/g_matlab: MATLAB once used to be my daily tool. After many years when I go back and read my old learning notes I felt maybe I still need it in the future. So, start this repo to keep some of my old learning notes servral …

opencv交叉编译,支持ffmpeg、libjpeg,实现取流及写入jpeg文件

一、准备工作 1、虚拟机交叉编译连 2、在虚拟机目录下创建工作目录&#xff0c;注意不要选择windows共享目录&#xff0c;比如这里选择&#xff1a; /home/cxyazhou/work 3、虚拟机安装cmake cmake-gui pkg-config&#xff0c;直接apt install即可 4、源码下载&#xff0c;需要…

Mongodb的部署

MongoDB下载包获取 https://www.mongodb.com/try/download/community 安装配置 第一步&#xff1a;在服务器 /usr/local 下创建 MongoDB 文件夹&#xff0c;用来存放安装包、服务以及之后 MongoDB 的数据库和日志文件。 cd /usr/local // 进入安装目录 mkdir MongoDB // 创…

【LeetCode: 2369. 检查数组是否存在有效划分 | 暴力递归=>记忆化搜索=>动态规划 | 线性dp】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

OpenCV(14)-OpenCV4.0中文文档学习2(补充)

相机校准和3D重建 相机校准 标定 findChessboardCorners() 它返回角点和阈值&#xff0c;如果成功找到所有角点&#xff0c;则返回 True。这些角落将按顺序放置&#xff08;从左到右&#xff0c;从上到下&#xff09;cornerSubPix()用以寻找图案&#xff0c;找到角点后也可以…

PHREEQC实践建模技术方法

PHREEQC软件为美国地质调查局基于C和C语言开发&#xff0c;面向一般地球化学、水文地球化学模拟的专业软件。该软件历经近30年迭代&#xff0c;功能不断完善&#xff0c;目前已发展成为-以PHREEQC为计算核心&#xff08;更新至3.7版本&#xff09;&#xff0c;辅以具备二次开发…

【无标题】docker安装jenkins安装流程(二)

配置Publish Over SSH JENKINS_URL/job/goods/build?tokenTOKEN_NAME http://xxxxx:8001/job/goods/job/goods/build?tokenxql1232.提交合并代码触发自动构建 http://xxxxx:8001/buildByToken/build?jobgoods&tokenxql123http://xxxxx:8001/buildByToken/build?jobgood…

Javaee 基于注解的AOP开发

基于注解的 aop 开发步骤&#xff1a; 1. 创建目标接口和目标类&#xff08;内部有切点&#xff09; 2. 创建切面类&#xff08;内部有增强方法&#xff09; 3. 将目标类和切面类的对象创建权交给 spring 4. 在切面类中使用注解配置织入关系 5. 在配置文件中开启组件…