【C++】C++入门(中)--引用

目录

一 引用概念

二 引用特性

三 常引用

四 引用使用场景

1 做参数

2. 做返回值

1 例一

2 例二

3 例三

4 例四

五 传值, 传引用效率比较

六  值和引用的作为返回值类型的性能比较

七 引用和指针的区别


一 引用概念

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

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

int main()
{int a = 1;int b = a;int& c = a;int& d = a;int& e = c;cout << &a << endl;cout << &c << endl;cout << &d << endl;cout << &e << endl;cout << &b << endl;return 0;
}

 引用类型必须和引用实体是同种类型的

二 引用特性

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

2. 一个变量可以有多个引用

3. 引用一旦引用一个实体,再不能引用其他实体

int main()
{int a = 0;// 引用必须初始化// int& b; 这是错误的int& c = a;int d = 1;// c变成d的别名?还是d赋值给c?--把d赋值给cc = d;// 一个对象可以有多个别名,可以别名继续取别名int& e = a;int& f = e;return 0;
}

三 常引用

void TestConstRef()
{const int a = 10;//int& ra = a;   // 该语句编译时会出错,a为常量 权限不能放大const int& ra = a;// int& b = 10; // 该语句编译时会出错,b为常量const int& b = 10;double d = 12.34;const double& rrd = d;//权限可以缩小//int& rd = d; // 该语句编译时会出错,类型不同const int& rd = d;//加了了const后 可以隐形类型提升int i = 1;double j = i;const double& rj = i;
}

 四 引用使用场景

1 做参数

// 传参数
void Swap(int* left, int* right)
{int temp = *left;*left = *right;*right = temp;
}void Swap(int& left, int& right)
{int temp = left;left = right;right = temp;
}typedef struct SListNode
{struct SListNode* next;int val;
}SLTNode, * PSLTNode;//void SListPushBack(PSLTNode& phead, int x)
void SListPushBack(SLTNode*& phead, int x)
{if (phead == NULL){// ... //phead = newnode;}else{// 找尾结点,再链接newnode// tail->next = newnode;}
}int main()
{int a = 0, b = 2;Swap(&a, &b);Swap(a, b);//PSLTNode plist = NULL;SLTNode* plist = NULL;SListPushBack(plist, 1);SListPushBack(plist, 2);SListPushBack(plist, 3);return 0;
}

我们可以看到插入的时候我们就没有传地址了. 接收的就是她本身, 只是换取了一个名字

引用类型必须和引用实体是同种类型的

2. 做返回值

1 例一

// 出了函数作用域,返回对象就销毁了,不能用引用返回,否则结果是不确定
int& Count()
{int n = 0;n++;return n;
}int main()
{int ret = Count();cout << ret << endl;cout << ret << endl;return 0;
}

 2 例二

// 出了函数作用域,返回对象就销毁了,不能用引用返回,否则结果是不确定
int& Add(int a, int b)
{int c = a + b;return c;
}int main()
{int& ret = Add(1, 2);//这里ret本质也是c的别名cout << "Add(1, 2) is :" << ret << endl;Add(3, 4);cout << "Add(1, 2) is :" << ret << endl;return 0;
}

3 例三

int& Add(int a, int b)
{static int c = a + b;//静态变量 只接受一次初始值return c;
}int main()
{int& ret = Add(1, 2);cout << "Add(1, 2) is :" << ret << endl;Add(3, 4);cout << "Add(1, 2) is :" << ret << endl;return 0;
}

4 例四

typedef struct SeqList
{int a[100];int size;
}SL;//void SLModify(SL* ps, int pos, int x)
//{
//     //...
//     assert(ps);
//     assert(pos < ps->size);
//     ps->a[pos] = x;
//}//引用做返回值:可以修改返回对象
int& SLat(SL* ps, int pos)
{assert(ps);assert(pos < ps->size);return ps->a[pos];
}int main()
{SL s;//...SLat(&s, 3) = 10;// 每个位置的值++for (size_t i = 0; i < s.size; i++){SLat(&s, i)++;}return 0;
}

这里SLat函数里的ps不是在此函数里定义的, 是在main函数定义传参过来的, 所以出了这个SLat函数, 返回值不会销毁, 所以可以引用返回.

怎样判断?

只要这个对象没有被定义在这个函数里, 即便函数执行结束了, 那么这个对象不会被销毁, 所以它的引用是存在的.

五 传值, 传引用效率比较

以值作为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直 接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值类型,效率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低。

#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;
}int main()
{TestRefAndValue();
}

六  值和引用的作为返回值类型的性能比较

#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 (size_t i = 0; i < 100000; ++i)TestFunc1();size_t end1 = clock();// 以引用作为函数的返回值类型size_t begin2 = clock();for (size_t i = 0; i < 100000; ++i)TestFunc2();size_t end2 = clock();// 计算两个函数运算完成之后的时间cout << "TestFunc1 time:" << end1 - begin1 << endl;cout << "TestFunc2 time:" << end2 - begin2 << endl;
}
int main()
{TestReturnByRefOrValue();
}

引用返回秒杀值返回

七 引用和指针的区别

在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。

指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。程序中使用指针,程序的可读性差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作

int main()
{int a = 10;// b是否开空间? -- > 没有int& b = a;// ptr开了空间int* ptr = &a;char ch = 'x';char& r = ch;cout << sizeof(r) << endl;return 0;
}

在底层实现上实际是有空间的,因为引用是按照指针方式来实现的。

引用表面好像是传值,其本质也是传地址,只是这个工作有编译器来做

引用和指针的不同点:

1. 引用概念上定义一个变量的别名,指针存储一个变量地址。

2. 引用在定义时必须初始化,指针没有要求 引用一旦定义时初始化指定,就不能再修改,指针可以改变指向

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

4. 没有NULL引用,但有NULL指针

5. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)

6. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小

7. 有多级指针,但是没有多级引用

8. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理

9. 引用比指针使用起来相对更安全

本节讨论的主要就是引用, 引用的重要性很大, 可以说贯穿了整个C++过程, 只不过现在肯定感受不到的, 要在后面类和对象的学习中, 才能深刻感受到它的作用和魅力, 有些是指针不能替代的. 最后还是那句话, C基础不扎实的看这个会困难, 可以看我之前C语言的博客.

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2015年亚太杯APMCM数学建模大赛B题城市公共交通服务水平动态评价模型求解全过程文档及程序

2015年亚太杯APMCM数学建模大赛 B题 城市公共交通服务水平动态评价模型 原题再现 城市公共交通服务评价是城市公共交通系统建设和提高公共交通运营效率的重要组成部分。对于公交企业&#xff0c;管理和规划部门&#xff0c;传统公交车站、线路和换乘枢纽的规划数据只是基于主…

深入探究ASEMI肖特基二极管MBR60100PT的材质

编辑-Z 在电子零件领域中&#xff0c;肖特基二极管MBR60100PT因其出色的性能和广泛的应用而显得尤为关键。理解其材质不仅有助于我们深入理解其运作原理&#xff0c;也有助于我们做出更合适的电子设计。那么&#xff0c;肖特基二极管MBR60100PT是什么材质呢? 首先&#xff0c…

【Ansible自动化运维工具 1】Ansible常用模块详解(附各模块应用实例和Ansible环境安装部署)

Ansible常用模块 一、Ansible1.1 简介1.2 工作原理1.3 Ansible的特性1.3.1 特性一&#xff1a;Agentless&#xff0c;即无Agent的存在1.3.2 特性二&#xff1a;幂等性 1.4 Ansible的基本组件 二、Ansible环境安装部署2.1 安装ansible2.2 查看基本信息2.3 配置远程主机清单 三、…

子集生成算法:给定一个集合,枚举所有可能的子集

给定一个集合&#xff0c;枚举所有可能的子集。 &#xff08;为简单起见&#xff0c;本文讨论的集合中没有重复元素&#xff09; 1、方法一&#xff1a;增量构造法 第一种思路是一次选出一个元素放到集合中&#xff0c;程序如下&#xff1a; void print_subset(int n, int …

Hafnium简介和构建

安全之安全(security)博客目录导读 目录 一、Hafnium简介 二、Hafnium构建 2.1.1 先决条件 2.1.1.1 构建Host 2.1.1.2 工具链 2.1.1.3 依赖 2.1.1.4 获取源码 2.1.2 构建 一、Hafnium简介 可信固件为Armv8-A、Armv9-A和Armv8-M提供了安全软件的参考实现。它为SoC开发人…

视频智能视觉分析真的遥不可及吗?有没有那种下载就能用的视频分析服务?

我一直有一个感觉&#xff0c;就是市面上很难找到那么一个带视频算法的软件&#xff0c;能让我们很直观地看到视频分析的效果&#xff0c;大部分都要内置在某种算力硬件上&#xff0c;或者对GPU要求比较严格&#xff0c;很难做到像以前我们做的视频直播软件那样&#xff0c;下载…

Java Dubbo 微服务框架 HP-SOA

HP-SOA 功能完备&#xff0c;简单易用&#xff0c;高度可扩展的Java微服务框架。 【快速开始】 技术架构 技术集成 Web服务框架&#xff1a;spring-boot 3.x微服务框架&#xff1a;Dubbo 3.x服务注册中心&#xff1a;Nacos配置中心&#xff1a;Nacos服务治理中心&#xff1…

使用DBSyncer实现增量Mysql到Mysql的数据同步_DBSyncer1.2.4版本---数据同步之DBSyncer工作笔记006

之前都是用来postgresql到mysql的同步,需要配置postgresql的复制槽,对于mysq来说,需要配置: mysql启用binlog: https://gitee.com/ghi/dbsyncer/wikis/%E6%93%8D%E4%BD%9C%E6%89%8B%E5%86%8C/%E6%97%A5%E5%BF%97%E9%85%8D%E7%BD%AE%EF%BC%88%E6%95%B0%E6%8D%AE%E6%BA%90%EF%B…

vscode 保存 “index.tsx“失败: 权限不足。选择 “以超级用户身份重试“ 以超级用户身份重试。

vscode 保存 "index.tsx"失败: 权限不足。选择 “以超级用户身份重试” 以超级用户身份重试。 操作&#xff1a;mac在文件夹中创建文件&#xff0c;sudo 创建umiJs项目 解决&#xff1a;修改文件夹权限 右键文件夹

网络协议--DNS:域名系统

14.1 引言 域名系统&#xff08;DNS&#xff09;是一种用于TCP/IP应用程序的分布式数据库&#xff0c;它提供主机名字和IP地址之间的转换及有关电子邮件的选路信息。这里提到的分布式是指在Internet上的单个站点不能拥有所有的信息。每个站点&#xff08;如大学中的系、校园、…

Vs2019 配置全局公共库和头文件

本文参考&#xff1a;Visual Studio 2019 配置全局公共库目录 背景 在程序开发过程中&#xff0c;日志和数据格式化是必不可少的。而spdlog和fmt正好可以满足这两点并且轻量。但是如果每次新建一个项目都必须引入一次显的太繁琐。那么是否可以加入vs的公共库呢? 实施 spdlog…

Java多线程篇(12)——ForkJoinPool

文章目录 1、基本原理2、源码2.1、sumbit干了啥&#xff1f;submitexternalPushsignalWorktryAddWorker 2.2、工作线程如何运行&#xff1f;怎么窃取&#xff1f;runWorkerscan 2.3、fork干了啥&#xff1f;fork 2.4、join干了啥&#xff1f;joinawaitJoin 1、基本原理 假设有…

《动手学深度学习 Pytorch版》 10.4 Bahdanau注意力

10.4.1 模型 Bahdanau 等人提出了一个没有严格单向对齐限制的可微注意力模型。在预测词元时&#xff0c;如果不是所有输入词元都相关&#xff0c;模型将仅对齐&#xff08;或参与&#xff09;输入序列中与当前预测相关的部分。这是通过将上下文变量视为注意力集中的输出来实现…

PS软件 点击 “另存为 Web 所用格式” ,提示错误 无法完成操作 系统找不到指定路径

软件&#xff1a;Adobe Photoshop 问题&#xff1a; PS 点击 另存为 Web 所用格式 &#xff0c;提示错误 无法完成操作 系统找不到指定路径 解决&#xff1a; 如果是Win10以上的系统&#xff0c;出现这种情况基本就是被系统自带的杀毒软件阻止了&#xff0c;可以看一下电脑右…

JavaScript从入门到精通系列第二十五篇:JavaScript中的Date对象

文章目录 一&#xff1a;Date对象简介 1&#xff1a;概念简介 二&#xff1a;Date对象 1&#xff1a;创建当前时间 2&#xff1a;创建指定时间 三&#xff1a;日期对象函数 1&#xff1a;getDate() 2&#xff1a;getDay() 3&#xff1a;getMonth() 4&#xff1a;getF…

vue源码分析(二)——vue的入口发生了什么

文章目录 前言&#xff08;1&#xff09;vue 项目构建的时候&#xff0c;通过package.json文件看到构建入口&#xff08;2&#xff09; 构建入口页面&#xff1a;导入同级模块config的getAllbuilds方法&#xff08;3&#xff09; 通过传入参数中的builds对象使用map获取&#x…

主流大语言模型的技术细节

主流大语言模型的技术原理细节从预训练到微调https://mp.weixin.qq.com/s/P1enjLqH-UWNy7uaIviWRA 比较 LLaMA、ChatGLM、Falcon 等大语言模型的细节&#xff1a;tokenizer、位置编码、Layer Normalization、激活函数等。2. 大语言模型的分布式训练技术&#xff1a;数据并行、…

threejs(4)-纹理材质高级操作

一、纹理重复_缩放_旋转_位移操作 // 导入threejs import * as THREE from "three"; // 导入轨道控制器 import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js"; // 导入lil.gui import { GUI } from "three/examples/jsm/l…

创建并启动华为HarmonyOS本地与远程模拟器及远程真机

1.打开设备管理器 2.选择要添加的手机设备,然后点击安装 3.正在下载华为手机模拟器 4.下载完成 5.创建新模拟器 下载系统镜像 点击下一步,创建模拟器 创建成功 启动模拟器 华为模拟器启动成功 6.登陆华为账号并使用远程模拟器 7.使用远程真机

使用Selenium和Java编写爬虫程序

以下是一个使用Selenium和Java编写的音频爬虫程序&#xff0c;该程序使用了proxy的代码。请注意&#xff0c;这个示例需要在IDE中运行&#xff0c;并且可能需要根据您的系统和需求进行调整。 import java.io.IOException; import java.util.List; import java.util.concurrent…