深度分析c+引用的本质以及引用与指针的区别

news2024/11/19 18:18:04

文章目录

  • 引用的概念
  • 引用的定义
  • 引用的特性
  • 引用的权限问题
  • 引用的使用方式
  • 引用作参数
  • 引用作返回值
  • 指针的本质
  • 引用和指针的区别

引用的概念

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。简单理解为:在语法层面上,引用就是给变量重新取一个名字

引用的定义

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟另外的内存空间进行存储,它与引用的变量共用的是同一块内存空间的地址。

格式如下:
类型& 引用变量名(对象名) = 引用实体;
而此处的&不是取地址操作符,而是起标志作用,标志所定义的标识符是个引用.

int main() {
    int a = 1;
    int& b = a; //此处就是引用的定义
    return 0;
}

此处就相当于变量a,b共用同一块内存地址空间
在这里插入图片描述

引用的特性

  1. 引用在定义时必须初始化
  2. 不能有空引用
  3. 一个变量可以有多个引用(相当于有多个别名)
  4. 引用一旦引用一个实体,不能引用其他实体
  5. 没有多级引用,再不能引用其他实体

如图
在这里插入图片描述

引用的权限问题

先看图代码
在这里插入图片描述

为什么图中不加const会发生报错呢???这就不得不提到引用的权限问题
接下来我们来分析一下

int main()
{
	const int a = 1;//变量a被const修饰,a的值不能改,权限是只读
	int&d = a;//d是a的别名,但d的改变会改变a,也就变成了可读可写,扩大了权限
	const int& d = a;//d被const修饰,所以d也只可读,权限与a相同,不存在扩大权限
	return 0;
}

所以之所以不加const会报错,就是因为权限被放大了

再看这个代码
在这里插入图片描述
这个代码能够顺利通过,为什么?

int main()
{
	int a = 1;//权限是可读可写
	const int& b = a;//b被const修饰,权限为可读,但不可写
	return 0;
}

通过这段代码我们可以得出,权限是可以被缩小的
注意:这段代码如果你想修改a的值,可以通过a来进行修改,但不能通过b,并且修改了之后,b的值仍然会跟随着a进行改变
如图:
在这里插入图片描述

接下来我们再看看一个特殊的例子

在这里插入图片描述
如果没有const这一行代码,可能大家会认为是a的类型(int)和b的类型(double)不匹配而导致的错误,但事实并非如此.当你加了const之后,便不会有报错,这是为什么呢?
这其中就要提到C语言中的类型转换(包括隐式类型转换和显式类型转换)
如下面这个例子
在这里插入图片描述
又比如:
在这里插入图片描述
总结:类型转换的时候都会产生一个临时变量,而这个临时变量是会被const修饰的,具有常性

所以现在我们知道了,上图那个例子报错就是因为权限被放大了,所以我们应该加上const

最后需要补充的是:权限问题只针对于引用和指针

引用的使用方式

1.引用普通变量(最常见的)

int main()
{
	int a = 10; //a是一个普通整型变量
	int & b = a;
    return 0;
}

2.常引用

int main()
{
    const int a = 1;
    const int& c = a;//保持权限相等
    const int& z =10;//常数只可读,所以要用const限制成只读
    return 0;
}

3.指针引用

int main()
{
		int a = 100;
		int* p = &a;
		int*& k = p;//这是个指针引用,k就是个指针p的别名
		return 0;
	
}

引用作参数

在使用带参函数的时候,由于一般函数的参数是实参的拷贝,但有些函数的操作可能是要对原变量进行改变的,C语言常用的做法是指针来传递原变量地址,这样的好处是如果需要将改变传回或者改变原变量则不需要返回值,可以通过传入指针直接改变。而C++提供了引用的新特性,可以使用引用传参
比如对于交换两数:

void swap(int *a, int *b)  //c语言的老方法
{
    int tmp = *a;
    *a = *b;
    *b = tmp;
}
void swap(int &a, int &b) //c++新引入的特性-引用
{
    int tmp = a;
    a = b;
    b = tmp;
}

其实在c++中分两种情况看待
①如果变量是内置类型,如char,int等,那么推荐值传递
因为编译器将直接使用寄存器进行操作,显然这是最快的,如果要用指针和引用,那么会多一次放存操作
②如果变量是对象,那么使用引用将是首选,并且参数里面的引用最好加上const
当需要传递的值很大,寄存器不够用时,那么使用指针或者引用,将只需要传递变量的地址就可以了

引用作返回值

说到传引用返回又不得不提到传值返回,那接下来我们对两者进行分析
1.对于传值返回,一般返回值都会建立一个临时变量,产生一个拷贝副本,而大多数情况下这个临时拷贝也是通过寄存器返回.
在这里插入图片描述
2.而传引用返回,不会产生值的副本,而是将其返回值直接传递给这个return后面的值(原因是因为本身是传引用返回,传的变量的别名,可以想成这个函数的最终效果就是一个变量),所以传引用返回可以直接当左值使用

//函数fun
int& fun()
{
   //...
}
//main函数
int main()
{
	fun()++; //当左值使用,直接进行++
	return 0;
}

指针的本质

在开始讲引用的概念时,我们强调了,在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间.但其实语法概念只是帮助我们更加方便的使用引用.
底层实现上实际是有空间的,引用的内部实现机制其实就是指针

通过下图底层汇编代码的角度也能够看到,指针和引用在底层汇编角度一模一样

在这里插入图片描述

指针和引用其实是一样的,但我们还能单独使用引用,原因就是编译器帮我们做了很多工作

就以上面代码为例:
int & ra = a;,编译器会自动转化成 int * const ra= a;(注意这是指针常数,这也解释了引用特性中的第4条为什么不能更改)
a = 20;,编译器会自动转化成 *a = 20;


下面这段引用的代码我们用底层指针进行分析

void func(int& ref)
//编译器发现参数为引用,便会转化成int* const ref = &a 
{
    ref = 100; //ref为引用,编译器转化为*ref = 100
}
int main()
{
    int a = 10;
    int& ref = a;
    ref = 20;//内部发现ref是引用,故编译器转为*ref = 20
    func(a);
    return 0;
}

总结:虽然引用的本质是指针但更为准确来说是加了const修饰的指针,也就是指针常量! ! !

引用和指针的区别

所以正是因为引用本质是指针,但又并非普通指针,所以引用和指针也就有了一些区别

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

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

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

相关文章

Oracle数据库SQL*Plus命令行执行SQL语句时,中文乱码报错解决方法

文章目录 问题背景解决方案1. 设置NLS_LANG环境变量2. 修改SQL*Plus字符集设置3. 使用Unicode字符集 常见错误和解决方法结语 🎉欢迎来到Java学习路线专栏~Oracle数据库SQL*Plus命令行执行SQL语句时,中文乱码报错解决方法 ☆* o(≧▽≦)o *☆嗨~我是IT陈…

【jmeter】接口测试流程

1、Jmeter简介 Jmeter是由Apache公司开发的一个纯Java的开源项目,即可以用于做接口测试也可以用于做性能测试。 Jmeter具备高移植性,可以实现跨平台运行。 Jmeter可以实现分布式负载。 Jmeter采用多线程,允许通过多个线程并发取样或通过独…

NTFS磁盘格式读写工具Tuxera NTFS 2023 for Mac中文破解版v2023含最新激活序列号

Tuxera NTFS 2023 Mac 是一个NTFS文件系统驱动程序,为解决Mac上不能对NTFS格式硬盘进行访问和读写而生。实现苹果Mac OS X系统读写Microsoft Windows NTFS文件系统,在硬盘、U盘等外接设备中进行全面访问、删除、修改等相关操作。 tuxera ntfs 2023 破解…

计算机网络第2章-CDN(4)

视频流和内容分发网 HTTP流和DASH 在HTTP流中,视频只是存储在HTTP服务器中作为一个普通的文件,每个文件有有一个特定的URL。当用户要看视频时,客户与服务器之间创建一个TCP连接并发送HTTP GET请求。 HTTP流具有严重缺陷,即所有…

扩大减产,NAND Flash市场迎来涨价潮 | 百能云芯

根据TrendForce的最新研究,NAND Flash市场即将面临一轮全面涨价的浪潮。供应商们通过严格控制产出量,将在第四季实施合约价的涨幅,预计在8%到13%之间。明年除非原厂仍能维持减产策略,且需留意服务器领域对Enterprise SSD需求是否回…

【Qt高阶】linux下编译提示找不到依赖的库【2023.10.16】

现象 提示找不到一些库文件。 排查方法 查看qmake出来的 makefile文件,相对路径是按照makefile文件所在路径进行查找。 命令行编译正常,拿QtCreator编译不过 把下面的勾去掉,直接在当前目录构建。

4.Vue-Vue调用第三方接口

题记 用vue调用第三方接口&#xff0c;以下是全部代码和操作流程。 寻找第三方接口网站 推荐&#xff1a;免费API - 提供免费接口调用平台 (aa1.cn) 下面的代码以下图中的接口为例 调用第三方接口代码 TestView.vue文件如下&#xff1a; <template> <div > <…

[nlp] chathome—家居装修垂类大语言模型的开发和评估

ChatHome: Development and Evaluation of a Domain-Specific LanguageModel for Home Renovation ChatHome: 家居装修垂类大语言模型的开发和评估 1、摘要: 我们的方法包括两个步骤:首先,使用广泛的家庭装修数据集(包括专业文章、标准文档和网络内容)对通用模型进行后预训…

【Operating Systems:Three Easy Pieces 操作系统导论 】抽象:地址空间

【Operating Systems:Three Easy Pieces 操作系统导论 】 早期系统 操作系统曾经是一组函数&#xff08;实际上是一个库&#xff09;&#xff0c;在内存中&#xff08;在本例中&#xff0c;从物理地址0开始&#xff09;&#xff0c;然后有一个正在运行的程序&#xff08;进程&…

记一次关于应用程序无法连接postgresql数据的问题排查

1. 完整的错误信息 could not connect to server: No such file or directory is the server running locally and accepting connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"? 2.排查过程 2.1.首先&#xff0c;我们先确保postgresql在运…

OpenHarmony创新赛丨报名倒计时,超强秘籍带你直通大奖!

OpenHarmony创新赛报名倒计时开始啦&#xff01; 设于开放原子全球开源大赛下的OpenHarmony创新赛&#xff0c;目前正在如火如荼地进行赛事招募中&#xff01;这次大赛围绕创新应用、商显行业、金融行业三大赛题&#xff0c;邀请来自企业、个人、高校师生等各界群体的优秀开发者…

浅谈安科瑞无线测温设备在俄罗斯某项目的应用

摘要&#xff1a;安科瑞ATE系列和ARTM-Pn无线测温设备适用于高低压柜的梅花触头&#xff0c;线缆&#xff0c;母排等位置对温度的实时监测。 Abstract: ATE series and ARTM-Pn are suitable for monitoring the real-time temperature of circuit breaker contact,cable,busb…

将license验证加入到系统中

1.将ClientDemo下的cn文件夹的内容导入项目对应的java目录下。 2.将license-config.properties文件导入resources目录下。 3.在项目的pom.xml中添加如下依赖。 <properties><!-- Apache HttpClient --><httpclient>4.5.5</httpclient><!-- License…

2023年【安徽省安全员C证】考试内容及安徽省安全员C证模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年【安徽省安全员C证】考试内容及安徽省安全员C证模拟考试&#xff0c;包含安徽省安全员C证考试内容答案和解析及安徽省安全员C证模拟考试练习。安全生产模拟考试一点通结合国家安徽省安全员C证考试最新大纲及安徽…

人工智能-推荐数据处理

数据处理 用户数据处理 用户数据一行 第一条数据是&#xff1a; 1::F::1::10::48067 首先&#xff0c;读取用户信息文件中的数据&#xff1a;接下来把用户数据的字符串类型的数据转成数字类型&#xff0c;并存储到字典中&#xff0c;实现如下&#xff1a;代码如下&#xf…

GitHub Action 通过SSH 自动部署到云服务器上

准备 正式开始之前&#xff0c;你需要掌握 GitHub Action 的基础语法&#xff1a; workflow &#xff08;工作流程&#xff09;&#xff1a;持续集成一次运行的过程&#xff0c;就是一个 workflow。name: 工作流的名称。on: 指定次工作流的触发器。push 表示只要有人将更改推…

【论文精读】Robust Speech Recognition via Large-Scale Weak Supervision

Robust Speech Recognition via Large-Scale Weak Supervision 前言Abstract1. Introduction2. Approach2.1. Data Processing2.2. Model2.3. Multitask Format2.4. Training Details 3. Experiments3.1. Zero-shot Evaluation3.2. Evaluation Metrics3.3. English Speech Reco…

Windows系统加密

Windows系统加密 这里类似一个简单的系统加密&#xff08;开机不插U盘&#xff0c;会在设定的时间后关机&#xff09; 小白教程&#xff0c;一看就会&#xff0c;一做就成。 1.看U盘在你电脑上的盘符 先把U盘插电脑上&#xff0c;看看U盘的盘符&#xff0c;我这里是H 2.在U…

深入浅出的介绍一下虚拟机VMware Workstation——part3(VMware快照)

虚拟机VMware使用 前言快照的原理快照的使用 前言 可以先查看之前的2篇博文&#xff0c;学习基础的虚拟机使用 深入浅出的介绍一下虚拟机VMware Workstation——part1 深入浅出的介绍一下虚拟机VMware Workstation——part2(详细安装与使用) 由于我们使用虚拟机的初衷就是用来…

磁盘数据恢复怎么操作?4个方法,亲测有效!

“谁能帮帮我啊&#xff01;我的电脑磁盘部分数据丢失了&#xff0c;是非常重要的数据&#xff0c;有什么方法可以找回来吗&#xff1f;最好是小白也能轻松操作的方法&#xff0c;感谢&#xff01;” 在我们的日常生活和工作中&#xff0c;磁盘数据恢复的技能变得越来越重要。当…