【c++】深入理解别名机制--引用

news2024/12/25 9:09:02

🌟🌟作者主页:ephemerals__

🌟🌟所属专栏:C++

目录

前言

一、引用的概念和定义

二、引用的特性

三、引用的实用性

1.引用传参

2.引用做返回值

2.1 引用做返回值的作用

2.2 引用坍缩问题、悬挂引用问题

四、const修饰引用

五、引用和指针的联系

总结


前言

        我们都知道,在c语言中,指针是一种功能十分强大的数据类型,它允许我们直接访问并且操作内存。然而,它在使用时稍有不慎,就会出错。对此,c++引入了一个新的概念:引用。引用可以实现部分类似于指针的功能,并且它比指针更加安全、简洁。

一、引用的概念和定义

        引用,作为c++中的一种特殊别名机制,当我们定义引用时,并不是创建了一个新变量,而是

给原有的变量起了一个别名。它的定义方式如下:

(数据类型)& 引用名 = 引用对象;

代码举例:

#include <iostream>
using namespace std;

int main()
{
	int a = 0;
	int& b = a;//定义引用,给a取了一个别名

	a++;

	cout << b << endl;
	
	b++;

	cout << a << endl;
	return 0;
}

运行结果:

可以看到,无论是对a自增,还是对b自增,它们表示的值都会发生改变。我们再来打印一下它们的地址:

cout << &a << endl;
cout << &b << endl;

结果显示它们的地址是相同的。这表明引用只是给变量起了一个别名,表示的还是同一块内存空间

我们画图表示一下引用:

二、引用的特性

        引用有以下三点语法特性:

1.引用在定义的时候必须要表明它所表示的对象。

2.由于引用是用作给变量取别名,所以一个变量可以有多个引用。当然,引用也可以有引用。

3.引用一旦指定了对象,就不能再指定其他对象

三、引用的实用性

        了解的引用的概念和特性之后,我们不禁会发出疑问:既然要对变量进行操作,直接修改不就好了嘛,何必还要取一个别名呢?

1.引用传参

        举一个例子:

#include <iostream>
using namespace std;

void Swap(int& x, int& y)
{
	int tmp = x;
	x = y;
	y = tmp;
}

int main()
{
	int a = 3;
	int b = 5;
	Swap(a, b);//交换a和b的值
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	return 0;
}

运行结果:

可以看到,使用引用传参,通过函数交换了变量a和b的值。由于引用是给变量起别名,所以此时的x和y就表示a和b本身。因此,我们在函数内部就实现了这两个元素的交换。相比传址调用,它的写法更加简单,并且在语法层面,引用是不开辟新内存的,减少了拷贝,节省了内存空间。

2.引用做返回值

2.1 引用做返回值的作用

        首先来看一段代码:

#include <iostream>
using namespace std;

int fun()
{
	static int a = 10;
	return a;
}

int main()
{
	fun()++;//报错
	cout << fun() << endl;
	return 0;
}

很显然,以上代码是不可行的。函数的返回值是一个临时变量,而临时变量具有常性,我们无法对这个值进行修改。但是引用做返回值可以做到这一点:

#include <iostream>
using namespace std;

int& fun()
{
	static int a = 10;
	return a;
}

int main()
{
	fun()++;
	cout << fun() << endl;
	return 0;
}

我们将返回值改成int的引用类型,则此时函数返回静态变量a的别名,所以我们让它自增,就相当于改变了a的值。

        有了引用做返回值,我们在调用函数的时候就可以通过这个返回值直接访问和修改原始对象,并且避免了临时变量的拷贝,增加程序运行的效率。

2.2 引用坍缩问题、悬挂引用问题

        刚才引用做返回值的方法虽然好用,但是难免会出现一些问题。举个例子:

#include <iostream>
using namespace std;

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

int main()
{
	int x = func();
	return 0;
}

虽然这里的func1函数返回了a的引用,但是我们却在主函数中以一个整形变量来接收,这里就会发生一种隐式的类型转换--引用坍缩,编译器会将这个返回值转换为它所引用的对象的一个临时拷贝这将导致我们无法访问并修改a的值,达不到预期效果。所以一定要以相同类型的引用来接收引用返回值

        再举一个例子:

#include <iostream>
using namespace std;

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

int main()
{
	int& x = func();
	return 0;
}

在func2函数中,我们创建了一个局部变量a并且返回它的引用,但是由于a是一个局部变量,当函数栈帧销毁时,变量a的空间已经被释放了,此时的返回值就变成一个悬挂引用(野引用),也就是说这个引用的主体已经不存在了,程序的运行结果就是未定义的。所以我们在使用引用做返回值时,一定要注意返回后的引用主体是否还存在

四、const修饰引用

        我们在定义引用时,可以在变量名之前加上const修饰(称之为常引用)。当一个引用被const修饰时,该引用就无法修改其所表示的对象。例如:

#include <iostream>
using namespace std;

int main()
{
	int a = 0;
	const int& b = a;
	a = 10;
	b = 20;//报错
	return 0;
}

注意:对于一个被const修饰的变量,定义它的引用时也需要用const修饰。例如:

#include <iostream>
using namespace std;

int main()
{
	const int a = 0;
	int& b = a;//报错
	const int& c = a;//正确
	return 0;
}

对于以下情况,定义引用时也必须要用const修饰:

#include <iostream>
using namespace std;

int main()
{
	int a = 5;
	const int& b = a * 3;//a*3是一个临时对象,具有常性,它的引用要用const修饰

	float c = 5.5f;
	const int& d = c;//当引用和对象的类型不同时,由于隐式类型转换的结果是一个临时对象,定义引用也需要用const修饰
	return 0;
}

五、引用和指针的联系

        引用和指针是相辅相成的,它们能够实现对方的部分功能,但是又不可完全替代。它们的一些联系和区别如下:

1.从语法层面上,引用是对一个对象取别名,不会开辟空间;而指针用于存储一个对象的地址,会开辟空间。

2.定义引用时,必须要指定表示的对象;而指针在定义时可以不指向对象。

3.引用不能改变表示的对象,而指针可以改变。

4.由于引用是对象的别名,所以可以直接通过引用访问对象;而指针则需要解引用才能访问对象。

5.相比指针,引用在使用上更加安全,不容易出现悬挂引用的问题。

6.在某些情况下,指针和引用在语义上可以相互替代,例如函数传参,都可以形成数据共享,并且避免内存的过度消耗。

总结

        今天,我们学习了引用。引用的功能十分强大,同时也弥补了指针的一些不足。深入理解引用对我们之后学习并实现类的相关功能有很大帮助。如果你觉得博主讲的还不错,就请留下一个小小的赞在走哦,感谢大家的支持❤❤❤

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

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

相关文章

ThreadPoolExecutor详解

恰逢经济下行&#xff0c;鄙人工作、生活日趋艰难&#xff0c;原本美好的愿望&#xff0c;如今只能成为奢望。不知如何是好的我&#xff0c;只能精研近几年来因浮躁而荒废的知识。今天就想跟大家聊一个对我来讲看似熟悉实则陌生的工具——ThreadPoolExecutor。熟悉是因为在我负…

【nacos 第二篇章】动手实践(从零代码开发版)

一、环境准备 本章将通过手把手的教程一步一步教你如何从零开发一个微服务应用。 首先需要安装好 nacos 服务并启动。安装 nacos 服务请看作者的 【nacos 第一篇章】安装一下 nacos 文章。 二、初始化项目 如上图所示&#xff0c;可以建立一个基础的项目。 搭建了基础项目之…

计算机毕业设计 在线项目管理与任务分配系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

节点使用简介:comfyui-photoshop

1、安装comfyui-photoshop 略过 一点要注意的是&#xff1a;在Photoshop上的安装增效工具&#xff0c;要通过Creative Cloud 桌面应用程序进行安装&#xff0c;才能成功在增效工具中显示&#xff0c;直接通过将文件解压到Plug-ins路径行不通&#xff08;至少对我来说行不通&am…

通过剪枝与知识蒸馏优化大型语言模型:NVIDIA在Llama 3.1模型上的实践与创新

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

阿里云ACP的三种报名与对应题库获取方式的详细说明(按费用排序)

文章目录 前言方式一、官方途径(较为昂贵)考试资格获取官方视频教程获取方式总结 方式二、报名机构(价格适中&#xff0c;考取速度快)推荐机构大概费用机构报名方式机构报名后所携带的内容或者说对于其他方法有什么优势总结 方式三、闲鱼(最便宜&#xff0c;但题库有风险)考试资…

C语言 之 strstr函数的使用和模拟、strtok函数的使用、strerror函数和perror函数的使用

文章目录 strstr 的使用和模拟实现strstr函数模拟实现 strtok 函数的使用例子1例子2例子3 strerror 函数的使用perror函数 strstr 的使用和模拟实现 函数原型&#xff1a; const char * strstr ( const char * str1, const char * str2 ); 该函数能够查找str1中第一次出现str2…

产业经济大脑建设方案(五)

为了提升产业经济的智能化水平&#xff0c;我们提出建设一个综合产业经济大脑系统&#xff0c;该系统通过整合大数据分析、人工智能和云计算技术&#xff0c;构建全方位的数据采集、处理和决策支持平台。该平台能够实时监测产业链各环节的数据&#xff0c;运用智能算法进行深度…

Unified 阻抗控制 architecture、framework、approach

Unified 阻抗控制&#xff08;Unified Impedance Control&#xff09;作为一种控制策略&#xff0c;其architecture&#xff08;架构&#xff09;、framework&#xff08;框架&#xff09;和approach&#xff08;方法&#xff09;为&#xff1a; 一、Unified 阻抗控制 Archite…

【MPC】模型预测控制 | 车辆优化控制策略研究与实践

写在前面&#xff1a; &#x1f31f; 欢迎光临 清流君 的博客小天地&#xff0c;这里是我分享技术与心得的温馨角落。&#x1f4dd; 个人主页&#xff1a;清流君_CSDN博客&#xff0c;期待与您一同探索 移动机器人 领域的无限可能。 &#x1f50d; 本文系 清流君 原创之作&…

CorelDRAW X4重磅发布更新!包含最新安装包下载

CorelDRAW X4是矢量图形制作工具软件&#xff0c;这个图形工具给设计师们提供了矢量动画、页面设计、网站制作、位图编辑和网页动画等多种功能。 X4版本的新特性有活动文本格式&#xff1a;仿效现有段落格式化、使文本能够贴齐格线框&#xff0c;或从边框缩排&#xff0c;从而获…

牛客JS题(四十四)根据包名,在指定空间中创建对象

注释很详细&#xff0c;直接上代码 涉及知识点&#xff1a; 地址引用assign 题干&#xff1a; 我的答案 <!DOCTYPE html> <html><head><meta charset"UTF-8" /><style>/* 填写样式 */</style></head><body><!--…

使用多种机器学习模型进行情感分析

使用 TF-IDF 与贝叶斯分类器进行情感分析是一个常见且有效的组合&#xff0c;特别是在文本分类任务中。贝叶斯分类器&#xff08;通常是朴素贝叶斯分类器&#xff09;等机器学习模型具有计算简单、效率高的优点&#xff0c;且在文本分类任务中表现良好。接下来&#xff0c;我将…

8.16作业

1.思维导图 2.在登录界面的登录取消按钮进行以下设置&#xff1a; 使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 将登录按钮使用qt5版本的连接到自定义的槽函数中&#xff0c;在槽函数中判断…

Solidworks二次开发:通过XYZ点的曲线

在SolidWorks中,通过XYZ点创建曲线是一种根据一组点的坐标生成三维曲线的方法。这种方法适用于需要根据特定点集设计曲线的情况,比如在建模复杂几何形状或执行逆向工程时。在SolidWorks中通过XYZ点创建曲线,操作步骤如下 打开SolidWorks并新建文件:启动SolidWorks软件,新建…

开放式耳机哪个品牌好用?盘点四款开放式蓝牙耳机排行榜前十名

作为网易云十级选手&#xff0c;测评过三十多款开放式耳机产品的开放式耳机测评专家来说&#xff0c;如果想要入手一款好用的开放式耳机的话&#xff0c;我会建议从三个方面来考虑&#xff0c;佩戴体验、音质效果和性能配置&#xff0c;了解这三个方面选购款好用的开放式耳机不…

Linux配置JDK8环境变量

目录 一、yum安装1.1 OpenJDK安装1.2 测试是否能够使用1.3 如何卸载JDK 二、手动安装2.1 下载2.2 上传到linux服务器路径2.3 解压2.4 配置环境变量2.5 测试是否能够使用 一、yum安装 1.1 OpenJDK安装 sudo yum install -y java-1.8.0-openjdk-devel1.2 测试是否能够使用 jav…

vue3+高德地图实现,创建和编辑多边形、圆形覆盖物(完整实现)

目录 一、绘制 1.形状选择 2.绘制图形 二、编辑 1.定义所需变量 2.获取需要编辑的覆盖物数据 fenceData并渲染 3.上述监听改动事件↓↓↓ 4.上述监听编辑结束事件 5.鼠标右击结束事件 初始化地图不再赘述,参考这篇文章 vue3中引入高德地图初始化,并添加、删除marke…

MySQL(四)——常用函数

文章目录 函数字符串函数数值函数日期函数流程函数 函数 函数&#xff0c;是指一段可以直接被另一段程序调用的程序或代码。 MySQL中内置了许多函数&#xff0c;我们只需在合适的场景下调用它们即可&#xff0c;调用函数查询结果直接使用SELECT即可&#xff0c;并且可以嵌套使…

电子电气架构---主流主机厂电子电气架构华山论剑(上)

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 屏蔽力是信息过载时代一个人的特殊竞争力&#xff0c;任何消耗你的人和事&#xff0c;多看一眼都是你的不…