C++系列-引用

引用

  • 引用的基本使用
    • 引用的起源
    • 引用的语法
    • 引用的本质
    • 引用的注意事项
    • 引用和指针
  • 引用作为函数参数
  • 引用作为函数的返回值
  • 常量引用
  • 其它
    • 用返回值方式调用函数(case 1)
    • 用函数的返回值初始化引用的方式调用函数(case 2)
    • 用返回引用的方式调用函数(case3)
    • 用函数返回的引用作为新引用的初始化值的方式来调用函数(case4)

引用的基本使用

引用的起源

  • 将变量名作为实参:值传递,改变形参,实参并不改变。
  • 将指针作为实参:实际上采用的也是值传递,只不过这里的值指的是变量的地址。
  • 传送变量的别名:传递的是变量的地址,所以二者本身完全是同一个地址的变量。

引用的语法

  • 数据类型 &别名=变量名
  • & 引用声明符,别名和原变量代表的是同一变量单元
  • 在传参数时,别名和原变量可以取同一个名字

引用的本质

  • 给变量起别名。
  • 引用的本质是一个指针常量(int * const p =&a;是个指针,该指针是常量)
  • 指针常量的指向不可更改,但是该地址内的值可以更改,这就是引用一旦初始化为某一变量的别名后,再不能更改的原因。

在这里插入图片描述

  • 在外部看,可以简化如下:

在这里插入图片描述

	code:#include <iostream>#include <string>using namespace std;int main(){int a = 666;int& b = a;		// 编译器内部自动转化为	int* const b = & a;b = 888;		// 发现是引用,自动转化为 *b=888;cout << "a的值:" << a << endl;system("pause");}
result:

引用的注意事项

  • 引用在声明时,必须同时初始化。
  • 必须引用合法的内存空间(int &a=10; 错的)。
  • 在声明一个变量的引用后,不能再作为其它变量的别名。
code:int a = 10;cout << "address of a:" << &a << ", value of a:" << a << endl;int x = 20;cout << "address of x:" << &x << ", value of x:" << x << endl;int & b = a;	//引用声明cout << "address of b:" << &b << ", value of b:" << b << endl;b = x;			//是变量赋值,而不是将该引用作为其它变量的引用	cout << "address of a:" << &a << ", value of a:" << a << endl;cout << "address of b:" << &b << ", value of b:" << b << endl;	result:address of a:000000D209FCFB34, value of a:10address of x:000000D209FCFB54, value of x:20address of b:000000D209FCFB34, value of b:10address of a:000000D209FCFB34, value of a:20		// a的值变为20address of b:000000D209FCFB34, value of b:20

引用和指针

  • 不必设立指针变量,指针变量要开坡另外的内存空间,其内容是地址。二引用变量不是第一个独立的变量,不单独占用内存空间。
  • 在函数调用时,并不需要再变量名前加取址符。
  • 在&a前面有类型时,是引用,如 int &a, 否则为取址符。
  • 改变形参,对于引用和指针,实参同时改变。

引用作为函数参数

  • 引用作为函数形参,形参改变,实参改变。
  • 不需要像指针那么复杂的操作。
值传递仅仅改变形参,实参不发生变化
code:
#include <iostream>
#include <string>
using namespace std;void swap(int x, int y)
{cout << "值传递swap之前:x, y分别为: " << x << "," << y << endl;int temp;temp = x;x = y;y = temp;cout << "值传递swap之后:x, y分别为: " << x << "," << y << endl;
}int main()
{int a1 = 666;int b1 = 888;cout << "值传递swap之前:a1, b1分别为: " << a1 << "," << b1 << endl;swap(a1, b1);cout << "值传递swap之后:a1, b1分别为: " << a1 << "," << b1 << endl;system("pause");return 0;
}result:值传递swap之前:a1, b1分别为: 666,888值传递swap之前:x, y分别为: 666,888值传递swap之后:x, y分别为: 888,666值传递swap之后:a1, b1分别为: 666,888
指针作为参数,传递的是实参的地址值,那么对该地址的操作,会影响到实参。
code:
#include <iostream>
#include <string>
using namespace std;void swap_pt(int *x, int *y)
{cout << "x, y地址分别为: " << x << "," << y << endl;cout << "值传递swap之前:*x, *y分别为: " << *x << "," << *y << endl;int temp;temp = *x;*x = *y;*y = temp;cout << "值传递swap之后:*x, *y分别为: " << *x << "," <<* y << endl;
}int main()
{int a1 = 666;int b1 = 888;cout << "a1, b1地址分别为: " << &a1 << "," << &b1 << endl;cout << "值传递swap之前:a1, b1分别为: " << a1 << "," << b1 << endl;swap_pt(&a1, &b1);cout << "值传递swap之后:a1, b1分别为: " << a1 << "," << b1 << endl;system("pause");return 0;
}result:a1, b1地址分别为: 00000006F5D4F904,00000006F5D4F924值传递swap之前:a1, b1分别为: 666,888x, y地址分别为: 00000006F5D4F904,00000006F5D4F924值传递swap之前:*x, *y分别为: 666,888值传递swap之后:*x, *y分别为: 888,666值传递swap之后:a1, b1分别为: 888,666
引用传递,实参和形参是同一变量
code:
#include <iostream>
#include <string>
using namespace std;void swap_reference(int &x, int &y)
{cout << "x, y地址分别为: " << &x << "," << &y << endl;cout << "引用传递swap之前:x, y分别为: " << x << "," << y << endl;int temp;temp = x;x = y;y = temp;cout << "引用传递swap之后:x, y分别为: " << x << "," << y << endl;
}int main()
{int a1 = 666;int b1 = 888;cout << "a1, b1地址分别为: " << &a1 << "," << &b1 << endl;cout << "引用传递swap之前:a1, b1分别为: " << a1 << "," << b1 << endl;swap_reference(a1, b1);cout << "引用传递swap之后:a1, b1分别为: " << a1 << "," << b1 << endl;system("pause");return 0;
}result:a1, b1地址分别为: 0000003871CFFB14,0000003871CFFB34引用传递swap之前:a1, b1分别为: 666,888x, y地址分别为: 0000003871CFFB14,0000003871CFFB34引用传递swap之前:x, y分别为: 666,888引用传递swap之后:x, y分别为: 888,666引用传递swap之后:a1, b1分别为: 888,666

引用作为函数的返回值

  • 要返回局部变量的引用。
  • 如果函数的返回是个引用,则函数的调用可以作为左值。
  • 不能返回函数内部通过new分配的内存的引用。
//不要返回局部变量的引用,局部变量在栈区,调用完毕后释放,有可能第一次使用该引用时,编译器可能还没释放,但是后面会出错
code:#include <iostream>#include <string>using namespace std;int & test(){int x = 100;return x;}int main(){int& ref = test();cout << "ref的值1:" << ref << endl;cout << "ref的值2:" << ref << endl;system("pause");}
result:ref的值1:632365056ref的值2:632365056
code:#include <iostream>#include <string>using namespace std;int& test_static(){static int x = 0;x += 666;return x;}int main(){int& ref = test_static();		// ref是函数中x的别名test_static() = 2000;			// test_static()返回的就是x的别名,相当对x=2000,cout << "ref的值:" << ref << endl;system("pause");}result:ref的值:2000

常量引用

  • 可以用于形参,防止误操作。
	code:#include <iostream>#include <string>using namespace std;int main(){int a = 666;//int& b = 888;			// 报错,必须引用合法的内存空间,888都不知道地址是什么const int &b = 888;		// 自动转化为 int temp = 888; const int &b = temp; 只能使用别名//b = 30;				// 不可再修改cout << "b的值:" << b << endl;system("pause");}
code:#include <iostream>#include <string>using namespace std;void print_data(const int& a){//a = 100;		//错误,已经不可再修改cout << "a = " << a << endl;}int main(){int a = 666;print_data(a);}
result:a = 666

其它

code:#include<iostream>using namespace std;float temp;float fn1(float r) {temp = r * r * 3.14;return temp;}float& fn2(float r) { //&说明返回的是temp的引用,换句话说就是返回temp本身temp = r * r * 3.14;return temp;}int main() {float a = fn1(5.0);			//case 1:返回值//float &b=fn1(5.0);		//case 2:用函数的返回值作为引用的初始化值 [Error] invalid initialization of non-const reference of type 'float&' from an rvalue of type 'float'//(有些编译器可以成功编译该语句,但会给出一个warning) float c = fn2(5.0);			//case 3:返回引用	float& d = fn2(5.0);		//case 4:用函数返回的引用作为新引用的初始化值cout << a << endl;//78.5//cout<<b<<endl;//78.5cout << c << endl;//78.5cout << d << endl;//78.5system("pause");return 0;}

用返回值方式调用函数(case 1)

  • 返回全局变量temp的值时,C++会在内存中创建临时变量并将temp的值拷贝给该临时变量。
  • 当返回到主函数main后,赋值语句a=fn1(5.0)会把临时变量的值再拷贝给变量a。
    在这里插入图片描述

用函数的返回值初始化引用的方式调用函数(case 2)

  • 函数fn1()是以值方式返回时,首先拷贝temp的值给临时变量。返回到主函数后,用临时变量来初始化引用变量b,使得b成为该临时变量到的别名。
  • 由于临时变量的作用域短暂(在C++标准中,临时变量或对象的生命周期在一个完整的语句表达式结束后便宣告结束,也就是在语句float &b=fn1(5.0);之后) ,所以b面临无效的危险,很有可能以后的值是个无法确定的值
    在这里插入图片描述
  • 可以如下操作:
code:int x=fn1(5.0);		//x不释放int &b=x;

用返回引用的方式调用函数(case3)

  • 函数fn2()的返回值不产生副本,而是直接将变量temp返回给主函数,即主函数的赋值语句中的左值是直接从变量temp中拷贝而来(也就是说c只是变量temp的一个拷贝而非别名) ,这样就避免了临时变量的产生。
  • 尤其当变量temp是一个用户自定义的类的对象时,这样还避免了调用类中的拷贝构造函数在内存中创建临时对象的过程,提高了程序的时间和空间的使用效率。

在这里插入图片描述

用函数返回的引用作为新引用的初始化值的方式来调用函数(case4)

  • 函数fn2()的返回值不产生副本,而是直接将变量temp返回给主函数。在主函数中,一个引用声明d用该返回值初始化,也就是说此时d成为变量temp的别名。
  • 由于temp是全局变量,所以在d的有效期内temp始终保持有效,故这种做法是安全的。

在这里插入图片描述

注意:
本文中的部分内容来自伯乐在线

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

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

相关文章

探工业互联网的下一站!腾讯云助力智造升级

引言 数字化浪潮正深刻影响着传统工业形态。作为第四次工业革命的重要基石&#xff0c;工业互联网凭借其独特的价值快速崛起&#xff0c;引领和推动着产业变革方向。面对数字化时代给产业带来的机遇与挑战&#xff0c;如何推动工业互联网的规模化落地&#xff0c;加速数字经济…

【Axure模板】APP帮助中心原型,在线客服意见反馈模块高保真原型

作品概况 页面数量&#xff1a;共 10 页 兼容软件&#xff1a;Axure RP 9/10&#xff0c;不支持低版本 应用领域&#xff1a;原型设计模板 作品申明&#xff1a;页面内容仅用于功能演示&#xff0c;无实际功能 作品特色 该模板作品为APP帮助与客服的通用模块&#xff0c;…

MySQL分页查询-性能优化

MySQL分页查询优化 一、背景二、原因三、解决四、原理探究 https://blog.csdn.net/hollis_chuang/article/details/130570281 一、背景 业务背景&#xff1a;给C端10万级别的用户&#xff0c;同时发送活动消息&#xff0c;活动消息分为6类。数据背景&#xff1a;mysql表有百万…

拒绝摆烂!C语言练习打卡第五天

&#x1f525;博客主页&#xff1a;小王又困了 &#x1f4da;系列专栏&#xff1a;每日一练 &#x1f31f;人之为学&#xff0c;不日近则日退 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、选择题 &#x1f4dd;1.第一题 &#x1f4dd;2.第二题 &#x1f4d…

【高级IO】- 多路转接之 poll | epoll

目录 I/O多路转接 - poll poll 函数 poll 服务器 poll 服务器 poll 的优点 poll 的缺点 I/O 多路转接 - epoll epoll 的相关系统调用 epoll_create 函数 epoll_ctl 函数 epoll_wait 函数 epoll 工作原理 epoll 服务器 ​编辑 epoll 的优点&#xff08;与 sele…

在线零售供应链管理:从0到100

全球57%的公司将其供应链视为竞争优势&#xff0c;然而只有6%的人表示完全了解它。无论您是首次在线卖家还是经验丰富的专业人士&#xff0c;驾驭管理高效且具有成本效益的零售供应链的复杂性都可能具有挑战性。一起来了解一下吧&#xff01; 供应链管理是什么&#xff1f;它基…

html动态爱心代码【二】(附源码)

目录 前言 效果演示 内容修改 完整代码 总结 前言 七夕马上就要到了&#xff0c;为了帮助大家高效表白&#xff0c;下面再给大家带来了实用的HTML浪漫表白代码(附源码)背景音乐&#xff0c;可用于520&#xff0c;情人节&#xff0c;生日&#xff0c;表白等场景&#xff0c…

前端打开弹窗时将链接转化为二维码

qrcodejs2 1.安装qrcodejs2 2.在使用页面中引入 import QRCode from "qrcodejs2";3.在组件中注册(Vue2项目) components: {QRCode,}, 4.在data中定义qrcode&#xff0c;以及方法中使用 showCode(row) {this.dialogVisible true;this.$nextTick(() > { 需要n…

21 移动测试神器:带你玩转Appium

Appium特点 Appium 作为目前主流的移动应用自动化测试框架&#xff0c;具有极强的灵活性&#xff0c;主要体现在以下 5 个方面&#xff1a; 测试用例的实现支持多种编程语言&#xff0c;比如 Java、Ruby、Python 等&#xff1b; Appium Server 支持多平台&#xff0c;既…

算法基础(1):排序和查找算法

1、排序算法 1.1、堆排序(大顶堆)-重点&#xff1a; 参考文章&#xff1a;堆排序1、堆排序二 前置知识&#xff1a; 大顶堆&#xff1a;完全二叉树&#xff0c;且父节点大于左右儿子&#xff0c;左右子树又是大顶堆&#xff0c;依赖数组来实现(vector)第一个节点的父节点&…

QT中按钮的基类QAbstractButton

QT中按钮的基类QAbstractButton 关于控件类的学习方法继承关系信号槽函数标题和图标按钮的 Check 属性 关于控件类的学习方法 控件类很多&#xff0c;API更多&#xff0c;但是不需要记忆知道控件对应的类名&#xff0c;通过帮助文档随用随查优先看帮助文档中控件对应的信号和槽…

LeetCode算法心得——k-avoiding 数组的最小总和(标记数组)

大家好&#xff0c;我是晴天学长&#xff0c;这是一个细节题和一部分的思维题哈&#xff01; 2) .算法思路 k-avoiding 数组的最小总和 1,填充一个1到n 的Boolean的数组 要n个数&#xff0c;但是数组大小不能确定。 所以建立1000的大小。 2.遍历筛选&#xff0c;如果数组中有这…

ubuntu18.04安装远程控制软件ToDest方法,针对官网指令报错情况

有时我们在家办公&#xff0c;需要控制实验室的笔记本&#xff0c;因此好用的远程控制软件会让我们的工作事半功倍&#xff01; 常用的远程控制软件有ToDesk&#xff0c;向日葵&#xff0c;以及TeamViewer&#xff0c;但是为感觉ToDesk更流畅一些&#xff0c;所以这里介绍一下…

MySQL之索引和事务

索引什么是索引索引怎么用索引的原理 事务使用事务事务特性MySQL隔离级别 索引 什么是索引 索引包含数据表所有记录的引用指针&#xff1b;你可以对某一列或者多列创建索引和指定不同的类型&#xff08;唯一索引、主键索引、普通索引等不同类型&#xff1b;他们底层实现也是不…

Linux的基础指令

目录 1、ls指令 .和..意义 2、pwd指令 3、cd指令 ①cd ~ ②cd - 关于cd ..的用法 绝对路径和相对路径 4、touch指令 5、mkdir指令 tree指令 6、rmdir指令 7、rm指令 * 8、man指令 9、cp指令 nano&#xff1a; 10、mv指令 11、cat指令 12、more指令 13、less…

3d max省时插件CG MAGIC功能中的材质参数可一键优化!

渲染的最终结果就是为了让渲染效果更加真实的体现。 对于一些操作上&#xff0c;可能还是费些时间&#xff0c;VRay可以说是在给材质做加法的路上越走越远&#xff0c;透明度、凹凸、反射等等参数细节越做越多。 对于材质参数调节的重要性大家都心里有数的。 VRay材质系统的每…

万能的Python爬虫模板来了

目录 万能爬虫组成部分 示例代码 注意事项 总结 Python爬虫是一种强大的工具&#xff0c;可以帮助我们自动化地从网页中获取数据。无论是获取最新的新闻、实时的股票数据&#xff0c;还是进行网络数据分析&#xff0c;Python爬虫都能发挥重要作用。今天介绍一个万能python爬…

laravel aws s3

由于公司有境外项目&#xff0c;服务器、文件存储都是用的亚马逊&#xff0c;真真地是没有用过&#xff0c;在此记录一下自己的s3研究结果 Laravel - aws - s3 第一步创建用户&#xff0c;生成秘钥&#xff1a; 第二步创建存储桶&#xff1a; 1、创建存储桶时&#xff0c;以下…

思腾云计算

去年世界人工智能大会&#xff08;WAIC 2022&#xff09;上&#xff0c;只有屈指可数的几家大厂推出大模型&#xff0c;但在科技部新一代人工智能发展研究中心5月底发布的《中国人工智能大模型地图研究报告》显示&#xff0c;我国10亿参数规模以上的大模型已发布79个&#xff0…

redis数据类型详解+实例

redis中的数据类型&#xff1a; string&#xff0c;list, set, zset, hash,bitmaps, hyperloglog, gepspatial 目录 一、 String 二、List 三、Set 四、Zset 五、Hash 六、Bitmaps 七、Hyperloglog 八、Gepspatial 一、 String redis最基本的数据类型&#xff0c;一个…