IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++引用及其底层原理 -> 正文阅读

[C++知识库]C++引用及其底层原理

引用

在这里插入图片描述

引用不是定义一个新变量,而是给已存在的变量取了一个外号,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。
举个形象的例子,鲁智深又被叫做"花和尚",这里的花和尚和鲁智深都是同一个人,花和尚就是鲁智深的引用,说白了引用其实就是取外号。

引用的注意事项

1.引用必须初始化

int main()
{
int a;
int &b =a;
}
这时b就是a的外号。
下面的这种没有初始化的做法是错误的
int main()
{
int &b;//引用必须初始化,这里没有进行初始化。
}

2.一个变量可以有多个引用

在生活中,我们可能有多个名字,在家中父母可能叫你小名,在外面别人可能叫你的全名或者外号
其实也就是一个变量可以有多个外号,也就是可以有多个引用。
int main()
{
int a;
int &b=a;
int &c=a;
}
这里的b和c都是a的外号,b,c,a三个变量指向的都是同一块内存空间。

3.引用一旦引用了一个实体就不能再引用其他的实体

形象的来说,就是你和你的亲弟弟不能用同一个名字
下图c是a的引用,那么现在他就不能做b的引用了。
在这里插入图片描述

引用做参数

在讲引用做参数之前,我们先需要了解一下,参数传值和参数传引用的区别。

1.参数传值
下图实参传递了a,形参b对其进行了接收并修改,但是实参a最终并没有受到影响,这又是为什么呢?
在这里插入图片描述
原来,参数传值的时候,形参会生成一份实参数据的拷贝,也就是说实参和形参指向的不是同一块空间,所以形参的修改不会影响实参。
1185a4b76bd7d6280e1f0a119.png)
2.引用传参
下图进行了引用传参,形参的修改对实参产生了影响,我们可以大胆推测形参和实参是一块空间。
在这里插入图片描述
原来,引用传参的时候,形参不再是实参的拷贝,而是实参的一个引用,也就是说实参和形参指向的是同一块内存空间,形参的改变会影响实参。
在这里插入图片描述

实参传值和传引用的优劣

1.实参传值

缺点:形参会生成一份实参数据的拷贝,当数据量很大时,在一定程度上就会影响程序的运行速度
优点:因为形参是实参的拷贝,所以形参的操作不会影响实参,可以防止实参数据遭到污染。

2.实参传引用

缺点:形参的操作对实参会产生影响,形参的错误操作会让实参数据遭到修改。
优点:因为形参是实参的引用,一定程序上,可以提高程序的运行速度

引用做函数返回值

在了解引用做返回值时,我们还是得先了解传值返回和传引用返回的区别。其实原理和上面大致相同。
1.传值返回
在这里插入图片描述在这里插入图片描述
在返回c的时候,返回的不是c的本体,而是将c拷贝在一块临时空间里,所以返回的其实是这块临时空间。然后ret再次拷贝一个和这块临时空间一样数据的空间。
这块有点像俄罗斯套娃,需要多画图理解。我一开始也有点懵逼。多画图就清晰了。
但是问题又来了,这块临时拷贝空间又存储在哪里呢?
当c比较小的时候(4字节或者8字节),一般是存储在寄存器中。
当c比较大的时候,临时变量放在该函数的栈帧上面。

接下来我们通过观察代码的反汇编进行证明:

在这里插入图片描述
分析这段代码的汇编,在进入add函数以后,先是将a的值给了eax,然后将b的值加上a,接着将eax里的值给了c。最后对c进行返回,在返回c的时候生成一个临时拷贝,c将自己的值又给到了寄存器eax中。
在这里插入图片描述
最后回到主函数,eax将值给了ret。

传引用返回

在这里插入图片描述

这里进行的是传引用返回,也就是说ret其实就是c的别名。传引用返回,返回的就是本体,而不是拷贝。因为这里c是一个局部变量,在函数结束以后,栈帧被销毁,局部变量的空间被系统回收了。这时ret再去访问c的内容就可能造成非法访问,并且c的值可能已经被修改了。

形象的来说:就是你原先买了一个房子,后面你又将其卖给了别人,后面你想再次进入这个房子,但是这间房子已经不属于你了,你进房子的操作就属于非法访问了。

所以,传引用返回时,返回的对象不能是出函数就被系统回收的。也就是说返回的变量不能是一个局部变量。

引用的权限

1.引用的权限可以缩小
int main() {
int a = 10;
const int &b = a;//权限的缩小
}
这里变量a是可读可写的,而b是a的引用,b只能对a这块内存空间进行读取,不能进行修改,这就是权限的缩小,这在C++中是可以的。

2.引用的权限不能放大
int main() {
const int a = 10;
int &b = a;//权限的缩小
这里变量a指向的空间是只能读取的,不能进行修改,而a的引用b,是可以对a指向的这块空间进行修改的,使得权限得到了放大,这种语法在C++中是错误的。
}

总结:引用可以进行权限的缩小,但是不能进行权限的放大

引用经典笔试题

下图中的代码(1)和(2)是否能够正常运行?

double d=11.1;
int a=d;(1)
int &ret=d;(2)

答案:(1)可以运行通过,(2)不行。
代码(1)是普通的隐式类型转换。
而在了解代码(2)的错误原因之前,我们需要回顾一些知识:

产生临时变量的情况

1.类型转换
double d=11.1;
int a=d;
d的类型是double,a的类型是int,类型不同,正如下图所示,在发生隐式类型转换的时候,需要将d的值存到一个int类型的临时变量里,然后将这个临时变量的值赋予给a。
在这里插入图片描述
2.整形提升
int a=10
char c=‘b’;
if(a>c){
}
这里并不是拿c直接和a进行比较,而是将c赋值到一个int的临时变量里,通过这个临时变量去和a进行比较。

关于右值

结论:右值是具有常性的,是不可修改的。
这里的右值不能通过字面意思(处于式子右边的值)进行理解,以下的几种情况一般都是属于右值。
1.表达式的计算结果: 如:5+3=8,这里的8就是右值。
2.常量:如a=5,这里的5就是右值。
3.一些隐式类型转换产生的临时变量。如
int a;double d;d=a;
这里隐式类型转换产生的临时变量也是一种右值。

在明白了这些基础原理以后,我们开始学习为什么代码int &ret=d;(2)是错误的。

这里引用的变量其实是一块临时空间,而临时空间是右值是不能修改的,这种引用的方式本质上其实就是权限的放大,因此编译不能通过。
在这里插入图片描述

引用的底层原理

int main() {
int a;
int &b = a;
int *p = &a;
}
这里通过调试模式观看这段代码的反汇编。
在这里插入图片描述
这里的lea是取地址的意思。
从汇编代码可以看出,在底成实现的时候,引用和指针的实现方式是一样的,所以说:
引用的底层是通过指针实现的

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-15 22:13:21  更:2022-03-15 22:16:38 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 4:58:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码