C++【引用】——串讲

article/2025/7/7 6:48:55

【引用】——串讲(视频89-94)

Note:
i.视频为黑马程序员C++视频,系列文章为视频听课笔记;
ii.引用不仅包含定义及简单应用,在类与对象…中也有涉及;
iii.难度指数:+++
iv.不论变量、函数名、标识符形式怎样复杂,只要我们考虑编程的本质是对内存的操作,对内存进行分析,一切逻辑都会变得清晰。

1.引用的基本语法
1)含义:给变量起别名
2)code格式:数据类型 &别名 = 变量名
例如:int &b = a,则b为变量a的引用,也是对引用b的初始化
3)内存图解:
定义引用,则建立内存关系
由图可见,若定义b为变量a的引用,则b可对变量a中存储的值进行操作。

2.引用的注意事项
1)引用定义则必须进行初始化
2)引用在第一次初始化后不可更改

3.引用做函数参数(重点)
之前提到某封装函数被调用,传参时的传递方式分为按值传递或按地址传递,前者形参的改变不能改变实参的值,后者形参的改变可以改变实参的值;或者说前者形参不能修饰实参,后者形参可以修饰实参。

实际上,按地址传递实际上是传递的是指针,其记录实参的地址,因此可以实现对实参的修饰。引入“引用”的概念之后,可利用其作为函数参数实现对实参的修饰。

至此,函数被调用时,参数的传递方式有以下几种:
1)值传递
2)地址传递
3)引用传递
举例:以完成实参值的交换为例
1)值传递

#include<iostream>
#include<string>
using namespace std;
//定义值传递交换函数
void swap01(int a,int b)
{//值传递交换函数无法实现实参的交换int temp = a;a = b;tmep = b;cout << "值传递形参a=" << a << endl;//a=20cout << "值传递形参b=" << b << endl;//b=10
}
int main()
{int a = 10;int b = 20;swap01(a, b);cout << "值传递交换后实参a=" << a << endl;//a=10cout << "值传递交换后实参b=" << b << endl;//b=20
}

依靠值传递交换函数,无法实现实参的交换。

2)地址传递

#include<iostream>
#include<string>
using namespace std;
//定义地址传递交换函数
void swap02(int *a,int *b)
{//地址传递交换函数可以实现实参的交换int temp = *a;*a = *b;tmep = *b;cout << "地址传递形参a=" << a << endl;//a=20cout << "地址传递形参b=" << b << endl;//b=10
}
int main()
{int a = 10;int b = 20;swap02(&a, &b);cout << "地址传递交换后实参a=" << a << endl;//a=20cout << "地址传递交换后实参b=" << b << endl;//b=10
}

依赖地址传递交换函数,可以实现实参的交换。

3)引用传递

#include<iostream>
#include<string>
using namespace std;
//定义引用传递交换函数
void swap03(int &c,int &d)//定义形参c为a的引用,d为b的引用
{//引用传递交换函数可以实现实参的交换int temp = c;c = d;tmep = d;cout << "引用传递形参a=" << c << endl;//a=20cout << "引用传递形参b=" << d<< endl;//b=10
}
int main()
{int a = 10;int b = 20;swap03(a, b);//注意这里的实参,不需要加任何东西符号cout << "引用传递交换后实参a=" << a << endl;//a=20cout << "引用传递交换后实参b=" << b << endl;//b=10
}

依赖引用传递交换函数,可以实现实参的交换,形参作了实参的引用。

【总结】:
1)封装函数在没有返回值的情况下,要想实现对main函数中实参的操作,必须在封装函数中对其内存进行操作。
2)引用类似于指针的简化版本,它不像指针一样类似于一种数据类型,需要定义,有固定的含义,即存储的是内存地址。它更像是变量的分身,代替变量完成不能完成的对内存的操作。

4.引用做函数返回值(重点、难点)
Note:
1)不能返回局部变量的引用,但可以返回静态变量的引用。
【碎碎念】:总之,所有的注意事项都跟内存息息相关。

代码示例:

#include<iostream>
#include<string>
using namespace std;int& test01()//注意这里定义的函数返回值类型为引用
{int a = 10;//a为局部变量,存储在栈区,函数调用完之后,变量内存就被释放。return a;
}
int& test02()
{static int a = 100;//a为静态变量,存储在全局区,程序全部执行完毕后释放return a;
}
int main()
{//创建局部变量引用int &ref = test01();//ref为局部变量a的引用,但是由于a在函数执行完后即被释放,因此ref并没有可以操纵的内存cout << "作局部变量引用ref的值=" << ref << endl;//10,之所以输出10,是由于编译器对a保留一次的操作cout << "作局部变量引用ref的值=" << ref << endl;//乱码//创建静态变量引用	int &ref2 = test02();cout << "作静态变量引用ref的值="<< ref2 << endl;//100cout << "作静态变量引用ref的值="<< ref2 << endl;//100
}

2)函数的调用可以作为左值

代码示例:

#include<iostream>
#include<string>
using namespace std;int& test02()
{static int a = 100;//a为静态变量,存储在全局区,程序全部执行完毕后释放return a;
}
int main()
{//创建静态变量引用	int &ref2 = test02();cout << "ref2="<< ref2 << endl;//100cout << "ref2="<< ref2 << endl;//100//函数的调用作为左值test02() = 1000;//test02()可以看成a的引用cout << "ref2="<< ref2 << endl;//1000cout << "ref2="< ref2 << endl;//1000
}

从上面的例子中可以看到,函数test02()作为左值可以实现对静态变量的赋值操作。

5.引用的本质

1)定义:引用的本质是一个指针常量。
涉及到指针常量:指针的指向不可更改,但指向的内存中的值可更改。
易混淆的常量指针:指针的指向可以更改,但指向的值不可更改。
2)前面在引用的注意事项中提到,引用一旦初始化就不能更改,这也是跟引用的本质有关系,引用初始化时就确定了其指向,而其指向是不可更改的。
3)之所以引用的定义形式等跟指针不同,是因为在C++中,编译器对引用进行了包装,代码示例如下:

#include<iostream>
#include<string>
using namespace std;void func(int &ref)//等价于int * const ref = &a
{//等价于*ref = 20ref = 100;
}
int main()
{int a = 10;int &ref = a;//等价于int * const ref = &aref = 20;//ref为引用,内部编译器转换为*ref = 20cout << "ref:" << ref << endl;//20cout << "a:" << a << endl;//20func(a);cout << "ref:" << ref << endl;//100cout << "a:" << a << endl;//100return 0;
}

6.引用在类与对象中的应用(拓展、难点)

1)背景:创建类person,已知其中包含age属性以及personaddperson成员函数,该成员函数可以实现两个实例对象age属性的求和。
2)要求:创建实例对象p1p2,实现p2.age与若干个p1.age的连续相加。
3.1)示例介绍:

如代码示例一所示,成员函数personaddperson的函数类型为person,从函数的输出结果中可以看到,每次调用成员函数时,this指针都指向不同的实例对象(从输出的地址可以看出),因此,代码示例一不能实现p2.age与若干个p1.age的连续相加,仅且只能实现一次相加,下一次调用时,this指针即指向由成员函数创建的新的实例对象(非p2)。

//代码示例一
class person 
{
public://有参构造函数person(int age){this->age = age;}person personaddperson(person &p)//返回为“类”{this->age += p.age;cout << "this指针" << this << endl;//输出每次成员函数调用时,this指向的对象地址cout << "this指向的年龄为:" << this->age << endl;//输出每次成员函数调用时,this指向对象的年龄return *this;}int age;
};void test01()
{person p1(10);person p2(10);p2.personaddperson(p1).personaddperson(p1).personaddperson(p1);cout << "p2对象年龄为:" << p2.age << endl;
}int main()
{test01();
}

当成员函数返回为类,输出结果为:
在这里插入图片描述

3.2)示例介绍

如代码示例二所示,成员函数personaddperson的函数类型为person&,从函数的输出结果中可以看到,每次调用成员函数时,this指针均指向实例对象p2(从输出的地址可以看出)。这可以理解为:当利用类的引用作为函数返回类型时,所有创建的示例对象都是p2的别名,因此实现了对p2内存的连续操作。因此,示例二可以实现p2.age与若干个p1.age的连续相加。return *this 实际上返回的就是this指针指向的实例对象。

//代码示例2person& personaddperson(person &p)//返回为“类”{this->age += p.age;cout << "this指针" << this << endl;//输出每次成员函数调用时,this指向的对象地址cout << "this指向的年龄为:" << this->age << endl;//输出每次成员函数调用时,this指向对象的年龄return *this;}

当成员函数返回为“类”的引用(代码示例如上),输出结果为:
在这里插入图片描述
【一点思考】:
1)在刚开始学习引用时,把引用单纯的勉强理解为变量的别名,当接触了引用在“类与对象”中的应用后,发现,引用可以是任何事物的别名,可以是类的别名,好像也可以是函数的别名等等。在本文6)的案例中,其作为p2实例对象的别名实现了对p2中age属性的连续操作。
2)之前我将指针可以看作一种数据类型,记为int/char... *,即可套用其他数据类型定义的模板。
同理,引用也可以看作一种数据类型,记为int/char/person &,这样可以帮助我们更好的理解代码。

文章来源:https://blog.csdn.net/weixin_44721375/article/details/123880116
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://chatgpt.dhexx.cn/article/YoGax9Tl.shtml

相关文章

CLIP 改进工作串讲(下)

CLIP 改进工作串讲&#xff08;下&#xff09; 本文为 CLIP 改进工作串讲&#xff08;下&#xff09;【论文精读】 的学习笔记。 图像生成 最近一年图像生成领域扩散模型大火&#xff0c;尤其是文本生成图像&#xff0c;DALL-E、imagen 等工作层出不穷&#xff0c;有机会专门…

操作系统串讲

前言 文章内容来源&#xff1a;东北大学的操作系统MOOC视频在操作系统的不同阶段&#xff0c;计算机的工作形式也不同&#xff0c;不要在一开始就将操作系统在心里预设成现代的 windows 或 linux 操作系统&#xff0c;以及将计算机预设成个人电脑等&#xff0c;防止代错对象、…

4.7串讲

4.7串讲 Java基础API 文章目录 4.7串讲 Java基础API字符串字符字符串StringBulider&#xff0c;StringBuffer 内存结构正则表达式字符字符类预定义字符类POSIX字符类&#xff08;仅US-ASCII&#xff09;java.lang.Character 类&#xff08;简单的 java 字符类型&#xff09;Uni…

计算机网络知识串讲复习(超全)

本篇我总结了学习计算机网络时必备的知识&#xff0c;可以用于巩固知识或者期末复习~~~如果觉得博主爆肝总结的不错&#xff0c;感谢点赞! 目录 1、计算机网络的几个发展阶段 2、计算机网络的组成 3、协议的概念 4、实体,协议,服务,和服务访问点 5、计算机网络的分类 6、…

CLIP改进工作串讲(上)

CLIP改进工作串讲&#xff08;上&#xff09; 本文为 CLIP 改进工作串讲&#xff08;上&#xff09;【论文精读】 的学习笔记。 CLIP 改进方向 语义分割 Lseg、GroupViT 目标检测 ViLD、GLIP v1/v2 视频理解 VideoCLIP、CLIP4clip、ActionCLIP 图像生成 VQGAN-CLIP、CLIPass…

毕业知识串讲

1. 京淘后端项目架构 1.1 数据库主从同步 1.1.1 业务需求说明 当数据库发生宕机的现象,如果配置了数据库主从同步,则可以从从库中获取现有记录,显示数据的恢复. 1.2 数据库主从同步原理 1.2.1 数据库冷备份 说明: 人工的将数据库文件定期导出,一式三份 如果其中一份丢失…

如何做好技术串讲

首先&#xff0c;如何做好演讲是个好话题&#xff0c;不过这过于大众的主题不想写&#xff0c;除非哪天能想到点 新意 再说&#xff1b; 其次&#xff0c;串讲和演讲有啥区别呢&#xff1f;其实也没啥区别&#xff0c;一会儿说说我自己的理解&#xff1b; 最后&#xff0c;什么…

软件开发过程与项目管理(8.软件项目质量计划)

软件开发过程与项目管理&#xff08;8.软件项目质量计划&#xff09; 课件 软件质量基本概念 质量定义 质量是满足要求的程度&#xff0c;包括符合规定的要求和满足顾客隐含需求。 软件质量定义 软件质量是软件满足明确说明或者隐含的需求的程度 质量与等级 质量与等级…

软件项目开发基本流程详解

软件项目开发流程图是用来详细描述了软件在开发过程中产品调研、设计、开发、测试等各个阶段中各个角色&#xff0c;包含产品经理、研发、测试、用户等需要处理的事情&#xff0c;以及在不同阶段可以达到哪种效果。那么&#xff0c;一款软件从研发到发布到底要经过哪些流程呢?…

嵌入式软件开发流程

根据使用的开发工具套件不同&#xff0c;软件开发流程会有差异&#xff0c;但主要步骤大致相同。对于使用宿主机&#xff08;PC&#xff09;的集成化开发环境&#xff0c;软件开发流程一般包括创建项目、添加文件、编译连接、下载调试等步骤&#xff0c;如下图所示。 图1&#…

软件项目开发流程以及人员职责,软件工程中五种常用的软件开发模型整理

文章目录 一、软件项目开发流程逻辑图开发流程需求分析概要设计详细设计编码测试软件交付验收维护 软件维护软件升级 软件项目开发流程以及人员职责软件工程中五种常用的软件开发模型整理软件系统开发流程七大详细步骤完整介绍 一、软件项目开发流程逻辑图 这张图应该清楚的说…

软件工程项目流程

软件工程项目流程 1.1 项目合作与成员 根据本项目的工作内容和范围,我们将成立一个20人左右的项目工作组来负责本项目的开发。 1.2 项目实施方法 项目管理的成效直接关系到整个项目的成败。尤其是实施与移动互联网有关的新技术应用项目,无论在国内和国外都是有一定难度的,更…

软件工程----开发大致流程

软件开发的流程 需求分析概要设计项目计划详细设计编码测试项目测试项目部署后期运维软件开发注意事项 不同的软件项目&#xff0c;有不同的需求侧重点&#xff0c;开发流程也是不一样的。比如开发一个大型Web电商项目&#xff0c;这个往往需要采用前后端分离的方式&#xff0c…

软件项目开发流程逻辑图

相关链接&#xff1a; 软件项目规划大纲知识点

软件项目的开发流程

一个项目的开发流程 软件开发流程(Software development process) 1.项目启动 1、项目组成立(公司成员、客户成员) 2、制定项目预期目标 3、制定项目计划周期 4、建立好项目组成员沟通机制 2.需求调研 1、创建调研计划、协调调研时间 2、收集客户资料,获取客户需求 …

软件项目开发流程

软件开发流程&#xff08;Software development process&#xff09; 首先 看一下基本软件项目开发流程图 其中 1.需求分析&#xff1a;通过对客户业务的了解和与客户对流程的讨论对需求进行基本建模&#xff0c;最终形成需求规格说明书。2.总体设计&#xff1a;通过分析需求信…

一个完整的软件项目开发流程,软件过程,软件生命周期

一、开发流程图 1、需求分析 结构化分析面向对象分析 2、原型设计 结构化设计面向对象设计 3、程序开发 结构化开发面向对象开发 4、程序测试 二、软件生命周期 软件分析 1、问题定义 确定好要解决的问题是什么&#xff08;what&#xff09;&#xff0c;通过对客户的访问…

软件项目开发的完整流程

APP早已与我们的生活息息相关&#xff0c;一款APP从开发到上线需要哪些步骤&#xff0c;开发一个APP要多长时间&#xff0c;今天和大家分享一下完整的开发流程。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1、需求的整理 和开发传…

软件开发的一般流程

说明&#xff1a; 最初所有的开发工作都是由后端工程师完成的&#xff0c;随着业务越来越繁杂&#xff0c;工作量变大&#xff0c;于是我们将项目中的可视化部分和一部分交互功能的开发工作剥离出来&#xff0c;形成了前端开发。 大约从2005年开始正式的前端工程师角色被行业所…

git创建分支及合并

git创建分支及合并 1、在远端创建自己的分支 2、在本地创建自己的分支,并切换到自己的分支 git branch newbranch git checkout newbranch 3、将远端和本地分支关联起来 git branch --set-upstream-toorigin/newbranch newbranch git pull 4、在本地分支修改代码&#xff…