【引用】引用的概念与基本使用原则
学习导航
- 一、引用的基本介绍
- 二、引用的基本特性
- 三、引用的基本原则
- ①引用类型和引用实体类型相同
- ②引用类型和引用实体类型不同
- 四、引用的基础应用
- ①对标传址操作
- ②作为返回值
一、引用的基本介绍
什么是引用?通俗的讲,引用就是"取别名",我们看下面的例子:
可以看到,引用并不会开辟新的空间。
二、引用的基本特性
特性①:必须有初始化
特性②:一个变量可以有多个引用
可以给别名取别名,但本质上都是对a的引用
特性③:一旦引用了一个实体,就不能引用其他实体
可以看到,之后b不会再引用实体c,只能对b做赋值修改
三、引用的基本原则
①引用类型和引用实体类型相同
引用的一个极其重要的基本原则是:对变量实体的读写权限只能缩小不能放大。我们在接下来的例子中来说明这个原则。
引用可以引用常量吗?答案是可以的。但是我们需要加上const来保证读写权限没有被放大:
✪代码分析
我们来分析这段代码我们需要注意到,引用就是给实体取的别名,二者在地址上是一样的,对别名的修改也会改变实体的值,所以我们在取别名的时候就要保证对引用的读写权限没有扩大。就像上面的例子,10是一个只读变量,如果不加上const,那么就意味着可以通过a来修改常变量10,这显示是不行的。
②引用类型和引用实体类型不同
引用类型必须和引用实体是同种类型吗?不一定!怎么理解这个问题呢?我们可以类比我们在C语言中学到的隐式类型转化,我们来分析中间的过程:
int main()
{double d = 6.66;int a = d;
}
为什么可以将类型为double的变量赋值给类型为int的变量呢?实际上这个赋值过程不是一步到位的,而是存在一个 “中间变量”。这个中间变量接收d的整数部分,最后再把这个中间变量拷贝给a。需要注意的是,这个中间变量具有常属性。引用也是同样的道理:
✪代码分析
a并不是直接引用d,而是引用这个中间变量。由于中间变量具有常属性,所以前面必须加上const修饰避免扩大读写权限。
通过取地址我们可以确认a没有引用d,从而也间接说明了中间临时变量的存在。
四、引用的基础应用
①对标传址操作
void swap(int& a, int& b)
{int tmp = a;a = b;b = tmp;
}int main()
{int a = 10;int b = 20;swap(a, b);return 0;
}
正是由于引用和引用实体存在互相改变的关系,所以我们可以用引用来替代传值操作。拿我们C语言中常写的swap函数举例,这样写起来是不是更爽了呢?
但如果设计的函数中需要传入常数,那么就必须在参数前面加上const,否则存在扩大实体读写权限的风险。经过实际测试,引用的效率和传址的效率是差不多的。
相应的,一些输出型参数也可以用引用来实现,例如:
int* sortArray(int* nums, int numsSize, int* returnSize){}
returnSize是我们的输出型参数,在C语言中我们只能通过传址的方式实现,现在用引用也可以实现这样的效果。
②作为返回值
int& count()
{static int n = 0;n++;return n;
}
用引用作为返回值和传统的方式相比有什么好处呢?我们先来谈谈传统的方式是如何传递返回值的:
- 首先将预备返回的值存储到临时变量,再将临时变量拷贝给用于接收函数返回值的变量
- 预备返回的变量小则用寄存器存储,变量大则则创建函数栈帧的时候预先为返回值创建存储空间
如果我们使用引用,那我们根本就不需要额外的临时空间和额外的拷贝,因为我们是通过引用直接对实体进行操作的,这可以提供程序的效率。
但是引用作为返回值只适合返回值出作用域不销毁的情况,如上面static修饰的n变量,如果我们我们引用的变量出函数作用域销毁,那我们实际上通过引用创建了间接的“野指针”。
int& Add(int a, int b)
{int c = a + b;return c;
}int main()
{int& ret = Add(1, 2);Add(3, 4);cout << "Add(1, 2): " << ret << endl;cout << "Add(1, 2): " << ret << endl;return 0;
}
ret的值可能是随机值也可能不是,取决于这块空间有没有被重新覆盖和使用。cout函数栈帧的创建覆盖了Add函数的函数栈帧,所以ret的值变成随机值了
再来看几个变式:
int& Add(int a, int b)
{static int c;c = a + b;return c;
}int main()
{int& ret = Add(1, 2);Add(3, 4);cout << "Add(1, 2): " << ret << endl;cout << "Add(1, 2): " << ret << endl;return 0;
}
变量c用static修饰后,这块空间出函数作用域后不会被销毁,不用担心被其他函数栈帧所覆盖
int& Add(int a, int b)
{static int c = a + b;return c;
}int main()
{int& ret = Add(1, 2);Add(3, 4);cout << "Add(1, 2): " << ret << endl;cout << "Add(1, 2): " << ret << endl;return 0;
}
注意static语句只在初始化时执行一次
【引用】引用的概念与基本使用原则相关推荐
- 2020-09-22C++学习笔记之引用1(1.引用(普通引用)2.引用做函数参数 3.引用的意义 4.引用本质5.引用结论 6.函数返回值是引用(引用当左值)7测试代码)
2020-09-22C++学习笔记之引用1(1.引用(普通引用)2.引用做函数参数 3.引用的意义 4.引用本质5.引用结论 6.函数返回值是引用(引用当左值)7测试代码) 1.引用(普通引用) 变量 ...
- 【C++ 语言】引用 ( 引用简介 | 指针常量 | 常量指针 | 常引用 | 引用参数 | 引用 指针 对比 )
文章目录 I . 引用概念 II . 引用声明 III . 引用 地址 内存 分析 IV . 常引用 V . 引用作为参数 VI . 引用 与 指针 对比 I . 引用概念 C++ 对 C 扩充 : ...
- 引用和指针概念及区别
一.引用和指针 指针:指针是一个特殊的变量,它里面存储的的数值为内存里的一个地址,通过*访问内存地址所指向的值 引用:引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存 ...
- 2-5:C++快速入门之引用,引用和指针的区别
文章目录 (1)引用的概念 (2)引用的特点 (3)常引用 (4)引用的应用场景 A:做参数 B:做返回值 (5)引用和指针 在第一次学习C语言指针时,许多教材上都会给出一个交换两个变量值的例子,开始 ...
- 【Android 内存优化】Bitmap 内存缓存 ( Bitmap 内存复用 | 弱引用 | 引用队列 | 针对不同 Android 版本开发不同的 Bitmap 复用策略 | 工具类代码 )
文章目录 一.Bitmap 复用池 二.弱引用 Bitmap 内存释放 三.从 Bitmap 复用池中获取对应可以被复用的 Bitmap 对象 1.Android 2.3.3(API 级别 10)及以 ...
- C 语言结构体引用,引用 C 语言结构体学习
引用 C 语言结构体学习 这篇文章很基础,是个学习的好资料,所以收藏了: 1.直接声明结构体变量: struct{ int length; int width; }box1; 这样就声明了一个名为bo ...
- java 引用 引用的对象,Java 引用类型简述
强引用 ( Strong Reference ) 强引用是使用最普遍的引用.如果一个对象具有强引用,那垃圾回收器绝不会回收它.当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误 ...
- 字体设计的概念、意义与原则
字体设计的概念 文字是一个极其庞大的体系,蕴含着人类集体的智慧,而且对人类社会文明起到了见证作用,西方的文明孕育出拉丁字母,东方的文明诞生了中国汉字. 在字体设计中,首先是将字体定位,对收集到的相关资 ...
- 引用 引用 引用 学会求知 学会共处 学会做人 学会做事
◆学历不等于能力和水平,学校学到的在社会能用上的只有15%,而在社会能学到85%. ◆世上很多发生的事必有其原因,必有其结果,必有其收获. ◆心态归零,天道酬勤. ◆老板是私营企业家,赚了小钱是自己的 ...
最新文章
- 重磅:Python/Java/C 2020年之争!谁是你心中的NO.1?
- 最小割 ---- 二分图最大独立集(集合冲突模型) ---- 骑士共存 方格取数(网络流24题)
- 2021.12.17自制望远镜调焦座材料
- 如何设计一个安全对外的接口
- 怎么将翼型导入catia_CATIA导入翼型出现了问题,翼型是在网上找的。说是样条线运算有问题 - 机械 - 小木虫 - 学术 科研 互动社区...
- Python查找列表中相加等于s的n个数字(combinations的使用)
- 算法学习(三)堆排序
- 正则表达式(三)操作符的运算优先级、全部符号的解释
- [我给Unity官方视频教程做中文字幕]beginner Graphics – Lessons系列之灯光介绍Lights...
- FANUC Robot 编程教程
- 数据分析软件SPSS22的授权及汉化
- C++ 优先队列 priority_queue 使用篇
- java闰年_编写java程序判断闰年。
- Win7中删除桌面IE图标
- 特征放缩(Feature scaling)
- 大数据时代的“被遗忘权”之争
- 【视频】谁说程序员无趣?这么多只有资深程序员才看懂的段子,会心一笑,深夜释放压力,随着视频哈哈哈哈哈笑出鹅声!
- 2022年全球及中国疏水阀行业头部企业市场占有率及排名调研报告
- 408计算机专业统考哪些科目,408计算机考研统考科目难度分析-计算机操作系统...
- c语言题库选择填空题,C语言题库(填空题部分)