C++:引用

 

目录

概念:

引用的使用格式:

引用特性:

常引用

 使用场景:

1、做参数

二级指针时的取别名 

一级指针取别名

一般函数取别名

2、做返回值

 函数返回值的原理:

引用的返回值使用:

引用和指针的对比: 

 语法层面:

底层:

概念:

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

int main()
{

   int a=0;

   // 引用,b就是a的别名
   int& b= a;

   cout <<&b<< endl;

   cout<< &a<< endl;


   return 0;
}

如上代码所示,引用符是&,但是要和C语言中的&区分,如上代码就第一个&是c++的,而第二个是C语言的 ,且我们开辟了一个空间,它叫做a ,同时他又叫做b,二者的空间地址都是一样的。

取别名的同时还可以给别名取别名!这就相当于把李逵叫铁牛的同时,又把李逵叫做黑旋风。

int main()
{

   int a=0;

   // 引用,b就是a的别名
   int& b= a;

   cout <<&b<< endl;

   cout<< &a<< endl;

   int& c= a;

   //给别名取别名,如给别名b取了个别名叫做d
   int& d= b;


   return 0;
}

引用的使用格式:

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

void TestRef()
{
    int a = 10;
    int& ra = a;//<====定义引用类型
    printf("%p\n", &a);
    printf("%p\n", &ra);
}

注意:引用类型必须和引用实体是同种类型的。 

引用特性:

  1. 引用在定义时必须初始化
  2. 一个变量可以有多个引用
  3. 引用一旦引用一个实体,再不能引用其他实体 

 最重要的是第三点!第三点通俗来讲就是,当一个空间A取了一个别名X,那么另一个空间B就不能取和A空间相同名字的别名,也就说空间B的别名不能取X。

1、引用必须初始化

int& b;//没有初始化,是错误的
b=c;

2、引用定义后,不能改变指向

int& b= a;
int c=2; 
b=c; //本意是相将c取一个别名,但是这个意思只有赋值的意思,这是常见错误!
     //且不能同时取一样名字的别名

常引用

关于常引用,当变量的前方加上了const 后,该变量就变成了常量,而对于常量而言,不论是加上了const的变量变成的,还是本身就是一个常量数值,它在引用时必须要加上const ,此外因为引用类型必须和引用实体是同种类型的,但是如果想要跨越类型引用,也必须加上const!

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;
    //int& rd = d; // 该语句编译时会出错,类型不同
    const int& rd = d;
}

 使用场景:

1、做参数

  • 当引用使用在函数的参数上时,引用的用法就和指针一样,指针是因为C语言的形参只是拷贝,所以在传参时需要传递数值的地址,并且需要使用指针来存储地址并指向地址。
  • 而引用是给变量取别名,空间地址是不变的,所以传递参数并且给它取了个别名使用和指针的用法是一样的!

二级指针时的取别名 

//* & phead 是指给传过来的指针取了别名进行下面的函数使用

void PushBack(struct Node*& phead,int x)
{
   phead = newnode;
}

int main()

{

    struct Node* plist = NULL;
    return 0;

}


一级指针取别名

void PushBack(struct pNode& phead,int x)
{
   phead = newnode;
}

int main()

{

    pNode plist = NULL;
    return 0;

}


一般函数取别名

void Swap(int& a,int& b)
{
    //...
}
int main()
{
   int x=0,y=1;
   Swap(x,y);
   return 0;
}

2、做返回值

 函数返回值的原理:

  • 如下图所示,在C语言中,ret 的值是调用了func函数,而func函数会返回一个a,但是按照函数栈帧来讲,mian空间里面开辟了一个空间,而func也开辟了空间。
  • 但是func的空间会随着的调用结束而销毁(作用域的生命周期),同时返回值a也在销毁的地方,所以相当于a销毁了,于是乎ret得到的是个不知道是什么的值。
  • 但是计算机也知道这个东西会这样的结果,所以a就会被计算机传到一个寄存器中,由寄存器保存并交给ret,所以ret拿到的是寄存器的地址和寄存器里面的东西。

引用的返回值使用:

引用的返回值必须使用在全局变量、静态变量、堆上变量否则会出问题。 

静态变量的 返回值的 引用使用方法 
//其中函数的前面是返回值的类型,而这里的返回类型是返回一个别名
//表示着返回了一个变量a的别名 a

int& func()
{
	static int a = 0;
	return a;
}

int main()
{
	int ret = func();
	cout << ret << endl;

	return 0;
}

 如果,返回值并未在上述中的区域出现,且贸然的使用引用,那么根据函数返回值的原理,主函数main 中的变量拿到的这个返回值是已经因为生命周期消失而消失的数值和地址,这个是不成立且得到的数值是随机性的!

就比如下面代码中的ret一样,拿到的并非是寄存器的地址和里面的数值,而是消失的空间地址和里面的数值,就和野指针一样,是一个“野别名”

错误示范!

int& func()
{
	int a = 0;
	return a;
}

int main()
{
	int ret = func();
	cout << ret << endl;

	return 0;
}

引用和指针的对比: 

 语法层面:

  1. 引用是别名,不开空间,指针是地址,需要开空间存地址
  2. 引用必须初始化,指针可以初始化也可以不初始化
  3. 引用不能改变指向,指针可以
  4. 引用相对更安全,没有空引用,但是有空指针,容易出现野指针,但是不容易出现野引用
  5. 在sizeof中含义不同:引用结果为引用类型的大小(如int&、double&等),但指针始终是地址空间所占字节个数(32 位平台下占4个字节)

底层:

  • 汇编层面上,没有引用,都是指针,引用编译后也转换成指针了
  • 在底层代码中,引用其实就是指针,或者说引用会转化为指针并且开辟空间 


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

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

相关文章

搭建AI问答和AI绘画小程序都需要做什么?

1、注册和认证小程序 在微信公众平台 注册&#xff0c;选择小程序类别即可。根据提示提交企业相关资质文件即可&#xff0c;注册后进行认证小程序&#xff0c;官方会收取300元认证费用。也可以私信我可以免掉300元认证费。 2、开通微信商家支付 认证通过后&#xff0c;在“功…

uniapp 使用echarts做折线图条形图。

提前10天把中烟活动做完了&#xff0c;以为能打酱油到除夕那天&#xff0c;结果又要做什么数据看板&#xff0c;方便烟草领导过年查看数据&#xff0c;还只给5天时间&#xff0c;真实压榨剥削啊&#xff0c;下辈子再也不‘拍黄片’了&#xff0c;不&#xff01;下份工作我就转前…

MySQL:函数

基本介绍 在MySQL中&#xff0c;为了提高代码重用性和隐藏实现细节&#xff0c;MySQL提供了很多函数。函数可以理解为别人封装好的模板代码。 在MySQL中&#xff0c;函数非常多&#xff0c;主要可以分为五类&#xff1a;聚合函数、数学函数、字符串函数、日期函数、控制流函数、…

Maven讲解

介绍 Maven是一个流行的构建工具和项目管理工具&#xff0c;它主要用于Java项目的构建、依赖管理和项目报告生成。Maven通过提供一致的项目结构、自动化的构建过程和强大的依赖管理&#xff0c;简化了项目的开发和维护过程。 下面是一些Maven的主要特点和用途&#xff1a; 项…

【算法】Knuth-Morris-Pratt 算法(KMP算法):一种在字符串中查找子串的算法

引言 KMP&#xff08;Knuth-Morris-Pratt&#xff09;算法是一个在字符串中查找子串的算法&#xff0c;由 Donald Knuth、Vaughan Pratt 和 James H. Morris 共同发明。这个算法的特点是在查找过程中&#xff0c;不会回溯主串&#xff0c;也不会重复扫描已经比较过的子串&…

2024年上海高考数学最后四个多月的备考攻略,目标140+

亲爱的同学们&#xff0c;寒假已经来临&#xff0c;春节即将到来&#xff0c;距离2024年上海高考已经余额不足5个月了。作为让许多学子头疼&#xff0c;也是拉分大户的数学科目&#xff0c;你准备好了吗&#xff1f;今天&#xff0c;六分成长为您分享上海高考数学最后四个多月的…

2024 高级前端面试题之 JS 「精选篇」

该内容主要整理关于 JS 的相关面试题&#xff0c;其他内容面试题请移步至 「最新最全的前端面试题集锦」 查看。 JS模块精选篇 1. 数据类型基础1.1 JS内置类型1.2 null和undefined区别1.3 null是对象吗&#xff1f;为什么&#xff1f;1.4 1.toString()为什么可以调用&#xff1…

燃烧的指针(三)

&#x1f308;个人主页&#xff1a;小田爱学编程 &#x1f525; 系列专栏&#xff1a;c语言从基础到进阶 &#x1f3c6;&#x1f3c6;关注博主&#xff0c;随时获取更多关于c语言的优质内容&#xff01;&#x1f3c6;&#x1f3c6; &#x1f600;欢迎来到小田代码世界~ &#x…

为什么需要使用线程池来创建线程?

当我们使用new Thread无限创建线程的时候 因为频繁的创建线程和销毁线程&#xff0c;cpu利用率会非常高 当cpu利用率达到100%的时候 那么没有可用的资源 让其他进程使用 那么其他进程访问就会导致卡顿 访问速度变慢 当我们使用线程池的时候 &#xff0c;cpu利用率就会降低&…

市场复盘总结 20240126

仅用于记录当天的市场情况&#xff0c;用于统计交易策略的适用情况&#xff0c;以便程序回测 短线核心&#xff1a;不参与任何级别的调整&#xff0c;采用龙空龙模式 昨日主题投资 连板进级率 27/105 25.7% 二进三&#xff1a; 进级率低 50% 最常用的二种方法&#xff1a; 方…

2024最新版Visual Studio Code安装使用指南

2024最新版Visual Studio Code安装使用指南 Installation and Usage Guide for the Latest Visual Studio Code in 2024 By JacksonML Visual Studio Code最新版1.85已经于2023年11月由其官网 https://code.visualstudio.com正式发布&#xff0c;这是微软公司2024年发行的的最…

vs2019报错MSB4019 找不到导入的项目“BuildCustomizations\CUDA 9.2.props”

在VS中执行生成&#xff0c;报错如下&#xff1a;严重性 代码 说明 项目 文件 行 禁止显示状态 错误 MSB4019 找不到导入的项目“D:\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\VC\v160\BuildCustomizations\CUDA 9.2.props”。请确认 Import 声明“D:\Microso…

Mybatis----分页

1.什么是分页 分页&#xff08;Pagination&#xff09;是指将大量数据划分为多个页面进行展示的一种技术手段。在数据量较大的情况下&#xff0c;将所有数据一次性显示在页面上会导致加载时间过长和页面过于庞大&#xff0c;影响用户体验和系统性能。分页技术通过划分数据为多…

Mac Monitor:一款为macOS安全研究量身定制的高级独立系统监控工具

关于Mac Monitor Mac Monitor是一款功能强大的高级独立系统安全监控工具&#xff0c;该工具专为macOS安全研究、恶意软件分类和系统故障排除而设计&#xff0c;主要基于Apple Endpoint Security&#xff08;ES&#xff09;实现其功能。 Mac Monitor能够收集各种类型的系统事件…

量化交易学习2(因子研究)

因子有效性检验 参考1 参考2 在多因子研究框架中&#xff0c;因子的有效性检验是不可避免的工作&#xff0c;其本质是衡量一个因子的选股能力。 目前学术界和业界普遍使用的两种方法&#xff1a; 相关性检验 因子的相关性检验即检验单因子和收益率之间是否存在相关性 IC值 计…

搜狐新闻客户端使用Kotlin之后对JSON解析框架的探索

本文字数&#xff1a;7488字 预计阅读时间&#xff1a;45分钟 01 引言 自2017年Google发布Kotlin语言之后&#xff0c;Android开发由原来的Java开始向Kotlin过度&#xff0c;目前绝大部分Android开发岗位基本要求就是熟练使用Kotlin。事实上&#xff0c;很多有着多年历史的项目…

单片机学习笔记---矩阵键盘

目录 矩阵键盘的介绍 独立按键和矩阵按键的相同之处&#xff1a; 矩阵按键的扫描 代码演示 代码模块化移植 Keil自定义模板步骤&#xff1a; 代码编写 矩阵键盘就是开发板上右下角的这个模块 这一节的代码是基于上一节讲的LCD1602液晶显示屏驱动代码进行的 矩阵键盘的介…

主成分分析(PCA)Python

实际问题研究中&#xff0c;常常遇到多变量问题&#xff0c;变量越多&#xff0c;问题往往越复杂&#xff0c;且各个变量之间往往有联系。于是&#xff0c;我们想到能不能用较少的新变量代替原本较多的旧变量&#xff0c;且使这些较少的新变量尽可能多地保留原来变量所反映的信…

Idea Community社区版如何添加Run Dashboard

最近在学习spring cloud&#xff0c;跟着视频添加run dashboard&#xff0c;发现里面介绍的方法无法适用于idea community(社区版)。 然后自己研究了一下&#xff0c;成功添加&#xff0c;下面分享自己的方法。 如图&#xff0c;我的项目里添加了两个module&#xff0c;我想通…

【c语言】详解操作符(下)

前言&#xff1a; 在上文中&#xff0c;我们已经学习了 原码、反码、补码、移位 操作符、移位操作符、位操作符、逗号表达式、下标访问[ ]、函数调用&#xff08; &#xff09;&#xff0c;接下来我们将继续学习剩下的操作符。 1. 结构成员访问操作符 1.1 结构体成员的直接访…