我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C++详细分析引用的使用及其底层原理

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

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最终并没有受到影响,这又是为什么呢?

原来,参数传值的时候,形参会生成一份实参数据的拷贝,也就是说实参和形参指向的不是同一块空间,所以形参的修改不会影响实参。

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++引用的使用内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C++详细分析引用的使用及其底层原理

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

C++引用怎么使用及底层原理是什么

本篇内容介绍了“C++引用怎么使用及底层原理是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!引用引用不是定义一个新变量,而是给已存在的变
2023-06-30

C语言函数调用底层实现原理分析

这篇文章主要介绍了C语言函数调用底层实现原理,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2023-02-24

详细分析mysql视图的原理及使用方法

前言: 在MySQL中,视图可能是我们最常用的数据库对象之一了。那么你知道视图和表的区别吗?你知道创建及使用视图要注意哪些点吗?可能很多人对视图只是一知半解,想详细了解视图的同学看过来哟,本篇文章会详细介绍视图的概念、创建及使用方法。 1
2022-05-25

Java中Set集合的使用和底层原理解析

这篇文章主要介绍了Java中Set集合的使用和底层原理,Set集合的功能上基本上与Collection的API一致,Set集合没有扩展额外的API,本文通过示例代码给大家详细讲解,需要的朋友可以参考下
2022-12-10

JavaScript中Promise的简单使用及其原理详解

Promise是ES6最重要的特性之一,今天小编就来带大家一起系统且细致的研究一下Promise的用法以及原理,感兴趣的小伙伴可以学习一下哦
2023-03-23

C++ 函数参数详解:传入机制的底层原理与应用场景

c++++ 函数参数传递机制:值传递:创建传递值副本,原始变量不受影响。引用传递:直接操作原始变量,允许修改。指针传递:通过地址访问变量,可修改指向变量或指向其他变量。应用场景:值传递:不修改数据的函数,如打印、计算。引用传递:修改数据的函
C++ 函数参数详解:传入机制的底层原理与应用场景
2024-04-27

JavaScript Object.defineProperty与proxy代理模式的使用详细分析

这篇文章主要介绍了JavaScript Object.defineProperty与proxy代理模式的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
2022-11-13

操作系统中的Hosts文件工作原理和作用及其详细介绍

一、什么是Hosts文件? Hosts是一个没有扩展名的系统文件,Hosts文件是一个用于存储计算机网络中节点信息的文件,它可以将主机名映射到相应的IP地址,实现DNS的功能,它可以由计算机的用户进行控制。可以用记事本等工具打开,其作用就是
2023-06-16

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录