【引用】——串讲(视频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 &,这样可以帮助我们更好的理解代码。

C++【引用】——串讲相关推荐

  1. 计算机excel表格相关考试视频,1189.5天通过职称计算机考试:Excel 2003中文电子表格(考点视频串讲+全真模拟).pdf...

    <<5天通过职称计算机考试:Excel 2003中文电子表格(考点视频 串讲+全真模拟)>> 猛点这里下载全部内容 目录: 第1章 Excel应用基础 考点1 Excel的启动 ...

  2. html5的技术串讲,Web前端开发职业标准串讲(初级).pdf

    Web前端开发职业技能标准串讲 初级 工业和信息化部教育与考试中心 Web前端开发职业技能等级标准 初级能力标准知识点解析 ➢1 Web页面制作基础 ➢2 HTML5和CSS3开发基础与应用 ➢3 J ...

  3. 李沐论文精读系列五:DALL·E2(生成模型串讲,从GANs、VE/VAE/VQ-VAE/DALL·E到扩散模型DDPM/ADM)

    文章目录 一. 前言 1.1 DALL·E简介 1.2 DALL·E2简介 1.3 文生图模型进展 二. 引言 2.1 摘要 2.2 引言&模型结构 三. 算法铺垫 3.1 GANs 3.2 ...

  4. 文章阅读总结:视频理解论文串讲(Li Mu+ Yi zhu)

    文章目录 视频理解论文串讲(文章末尾有多数文章的地址) 1. Hand-Craft ===> CNN : DeepVideo 2. Two-Stream 2.1 2014_Two stream ...

  5. JSD2212班第二次串讲-面向对象阶段

    1. 概述 系统介绍一下接下来阶段要学习的内容: 1.JAVA: 1.1 java语言基础 1.2 java面向对象阶段(很重要!起的承上启下!!) 1.3 API阶段(Application Int ...

  6. OPENGL ES 2.0 知识串讲 (10) ——OPENGL ES 详解IV(纹理优化)

    上节回顾 上一节学习了如何从一张原始图片中,获取生成纹理所需要的信息,然后根据这些信息,通过OpenGL ES API在GPU内存中生成了一张纹理,并且还介绍了纹理属性,知道了如何通过纹理坐标将纹理映 ...

  7. 计算机网络冲刺串讲,计算机应用基础串讲冲刺讲义(二)

    计算机应用基础串讲冲刺讲义(二) 分类:自考 | 更新时间:2016-07-07| 来源:中华网教育 9.下面列出的四项中,不属于计算机病毒特征的是 A.潜伏性 B.激发性 C.传播性 D.免疫性 1 ...

  8. 【狂神说】前端进阶串讲笔记总结

    [狂神说]视频学习--前端串讲 这个系列使得我能在 Html + css + js 的基础上,实现对高级框架和工具的知识过渡,特此积累总结. 参考笔记:https://www.kuangstudy.c ...

  9. Python 常见问题串讲

    Python 常见问题串讲 1.数据类型 数字类型: int整型.long长整型 (python 2).float浮点.complex复数.以及bool布尔值(0和1) bool类型: True和Fa ...

最新文章

  1. ipython怎么安装numpy_在TensorFlow教程中安装numpy后仍然无法导入
  2. 大数相关计算(c语言版)
  3. python后端设计_Python后端设计模式
  4. 《CMOS集成电路后端设计与实战》——第2章 集成电路后端设计方法
  5. 产品结构图、功能结构图、信息结构图,区别在这里
  6. C# WPF十个美观的界面设计展示
  7. 技术总监面试有什么技巧
  8. 《东周列国志》第七十回 杀三兄楚平王即位 劫齐鲁晋昭公寻盟
  9. 服务器无线桥接怎么设置,路由器怎么设置桥接方法 2个路由器无线桥接设置图解...
  10. 实现开启和关闭android移动网络
  11. 见猎心喜 浅尝辄止 偶有所得 不足为法
  12. SpringCloud系列之Eureka服务注册及发现
  13. 论文工具大全+软件简介
  14. 电脑端上有哪些免费好用的思维导图软件?
  15. vs为什么打了断点不断_2019年亚洲羽毛球锦标赛半决赛焦点对阵:陈雨菲vs山口茜 德查波/莎西丽vs王懿律/黄东萍 周天成vs石宇奇...
  16. 过一下hibernate4-3
  17. 通过PowerShell获取域名whois信息
  18. 体验墨西哥最爽的山间天浴
  19. 免费常用的快递物流查询api接口介绍
  20. 双录系统服务器地址怎么登陆,双录系统服务器地址怎么登陆

热门文章

  1. mallat算法分析及c语言实现,图像的Mallat算法分解(Matlab代码)
  2. 高师培训计算机心得体会,培训学习心得体会范文
  3. 有向图的强连通分量----------银河
  4. 堡垒主机有什么用?看了这篇博客你就懂了。
  5. 安装vmtools之后任然不能在虚拟机和主机之间复制粘贴的问题
  6. js qs序列化数据 npmi qs --save
  7. 程序员们为什么不能“面朝大海,春暖花开?”
  8. 非线性规划之分式规划
  9. X4扭曲字体或图形 coreldraw_CorelDRAW X4下载
  10. python语言无需翻译成_python实现谷歌翻译