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.mzph.cn/news/44079.shtml

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

相关文章

数据库--SQL关键字的执行顺序

数据库相关链接&#xff1a; 数据库--数据类型&#xff1a;http://t.csdn.cn/RtqMD 数据库--三大范式、多表查询、函数sql&#xff1a;http://t.csdn.cn/udJSG 数据库--MySQL增删改查&#xff1a;http://t.csdn.cn/xkiti 一、一条sql语句通常包括&#xff1a; select fro…

make系列之入门

一.欢迎来到我的酒馆 在本章节介绍make工具。 目录 一.欢迎来到我的酒馆二.什么是make三.make与Makefile四.如何写Makefile 二.什么是make 你可能会遇到一些名词&#xff1a;GNU&#xff0c;Linux&#xff0c;make。它们是什么&#xff0c;又有什么样的联系&#xff1f; …

正则表达式:贪婪与非贪婪模式

正则中的三种模式&#xff0c;贪婪匹配、非贪婪匹配和独占模式。 在这 6 种元字符中&#xff0c;我们可以用 {m,n} 来表示 &#xff08;*&#xff09;&#xff08;&#xff09;&#xff08;?&#xff09; 这 3 种元字符&#xff1a; 贪婪模式&#xff0c;简单说就是尽可能进行…

安卓框架中的常见问题汇总

目录 1.安卓操作系统的组件结构图如下 2.问题汇总 1.安卓操作系统的组件结构图如下 2.问题汇总 问题1&#xff1a;安卓框架中的库和应用程序框架之间什么关系&#xff1f; 在安卓系统中&#xff0c;应用程序框架层&#xff08;Application Framework&#xff09;是核心应用程…

SpringBoot + Vue 微人事权限组管理模块 (十四)

权限组前端页面制作 权限组管理角色和菜单之间关系&#xff0c;操作员管理着用户和角色之间的关系。 英文的输入框要有个前缀&#xff0c;SpringSecurity里角色英文名需要加一个ROLE_的前缀 上代码 <div><div class"permissManaTool"><el-input pla…

Java --- 二维数组

一、二维数组的定义 public class TwoArrayTest {public static void main(String[] args) {//二维数组声明与初始化//方式1&#xff1a;静态初始化int[][] arr new int[][]{{1,2,3},{1,2,3},{1,2,3}};//方式2&#xff1a;动态初始化int[][] arr2 new int[3][3];arr2[0][1] …

vsCode使用cuda

一、vsCode使用cuda 前情提要&#xff1a;配置好mingw&#xff1a; 1.安装cuda 参考&#xff1a; **CUDA Toolkit安装教程&#xff08;Windows&#xff09;&#xff1a;**https://blog.csdn.net/qq_42951560/article/details/116131410 2.在vscode中添加includePath c_cp…

Oracle Database12c数据库官网下载和安装教程

文章目录 下载安装Oracle自带的客户端工具使用 下载 进入oracle官网 点击下载连接之后右上角会有一个下载 我们只需要数据库本体就够了 运行这个下载器 等待下好之后即可 出现 Complete 之后代表下载成功&#xff0c;然后我们解压即可 安装 双击 双击setup.exe 根据…

借助Midjourney创作龙九子图

&#xff08;本文阅读时间&#xff1a;5 分钟&#xff09; 《西游记》中有这么一段描写&#xff1a; 龙王道&#xff1a;“舍妹有九个儿子。那八个都是好的。第一个小黄龙&#xff0c;见居淮渎&#xff1b;第二个小骊龙&#xff0c;见住济渎&#xff1b;第三个青背龙&#xff0…

【C# 基础精讲】LINQ to XML查询

LINQ to XML 是 C# 中用于查询和操作 XML 数据的强大工具。它允许您使用 LINQ 查询语法对 XML 文档进行查询、过滤、投影等操作&#xff0c;从而更加方便地处理 XML 数据。本文将详细介绍 LINQ to XML 的基本概念、常见操作以及示例&#xff0c;帮助您了解如何在 C# 中使用 LIN…

Learning to Super-resolve Dynamic Scenes for Neuromorphic Spike Camera论文笔记

摘要 脉冲相机使用了“integrate and fire”机制来生成连续的脉冲流&#xff0c;以极高的时间分辨率来记录动态光照强度。但是极高的时间分辨率导致了受限的空间分辨率&#xff0c;致使重建出的图像无法很好保留原始场景的细节。为了解决这个问题&#xff0c;这篇文章提出了Sp…

生成式AI系列 —— DCGAN生成手写数字

1、模型构建 1.1 构建生成器 # 导入软件包 import torch import torch.nn as nnclass Generator(nn.Module):def __init__(self, z_dim20, image_size256):super(Generator, self).__init__()self.layer1 nn.Sequential(nn.ConvTranspose2d(z_dim, image_size * 32,kernel_s…

JVM——StringTable面试案例+垃圾回收+性能调优+直接内存

JVM——引言JVM内存结构_北岭山脚鼠鼠的博客-CSDN博客 书接上回内存结构——方法区。 这里常量池是运行时常量池。 方法区 面试题 intern()方法 intern() 方法用于在运行时将字符串添加到内部的字符串池stringtable中&#xff0c;并返回字符串池stringtable中的引用。 返…

计算机组成与设计 Patterson Hennessy 笔记(二)MIPS 指令集

计算机的语言&#xff1a;汇编指令集 也就是指令集。本书主要介绍 MIPS 指令集。 汇编指令 算数运算&#xff1a; add a,b,c # abc sub a,b,c # ab-cMIPS 汇编的注释是 # 号。 由于MIPS中寄存器大小32位&#xff0c;是基本访问单位&#xff0c;因此也被称为一个字 word。M…

输入输出+暴力模拟入门:魔法之树、染色の树、矩阵、字母加密、玫瑰鸭

秋招实习刷题网站推荐&#xff1a;codefun2000.com&#xff0c;还有题解博客&#xff1a;blog.codefun2000.com/。以下内容都是来自塔子哥的~ 输入输出 2023.04.15-春招-第三题-魔法之树 //#include<bits/stdc.h> #include<vector> #include<iostream>usin…

Datawhale Django后端开发入门Task01 Vscode配置环境

首先呢放一张运行成功的截图纪念一下&#xff0c;感谢众多小伙伴的帮助呀&#xff0c;之前没有配置这方面的经验 &#xff0c;但还是一步一步配置成功了&#xff0c;所以在此以一个纯小白的经验分享如何配置成功。 1.选择要建立项目的文件夹&#xff0c;打开文件找到目标文件夹…

csapp archlab PartC满分解答

任务 修改ncopy.ys和pipe-full.hcl以尽可能的提高ncopy.ys的运行速度 思路 pipe-full.hcl&#xff1a; 实现iaddq指令&#xff08;家庭作业4.54&#xff09;实现加载转发&#xff08;家庭作业4.57&#xff09; ncopy.ys&#xff1a; 使用循环展开&#xff08;第5.8节&…

openai多模态大模型:clip详解及使用

引言 CLIP全称Constrastive Language-Image Pre-training&#xff0c;是OpenAI推出的采用对比学习的文本-图像预训练模型。CLIP惊艳之处在于架构非常简洁且效果好到难以置信&#xff0c;在zero-shot文本-图像检索&#xff0c;zero-shot图像分类&#xff0c;文本→图像生成任务…

windows服务器下java程序健康检测及假死崩溃后自动重启应用、开机自动启动

前两天由于项目需要&#xff0c;一个windows上的批处理任务&#xff08;kitchen.bat&#xff09;&#xff0c;需要接到mq的消息通知后执行&#xff0c;为了快速实现这里我们通过springboot写了一个jar程序&#xff0c;用于接收mq的消息&#xff0c;并调用bat文件。 本程序需要实…

缺少或找不到vcruntime140_1.dll的解决方法

某天&#xff0c;当我准备打开电脑上的一个应用程序时&#xff0c;突然收到一个错误提示&#xff0c;显示缺少了vcruntime140_1.dll文件。这个文件是一个重要的系统组件&#xff0c;它的丢失导致了我无法正常运行该应用程序。于是&#xff0c;我开始了一场寻找和修复旅程。然而…