c++阶梯之引用与内联函数

1. 引用

1.1 引用概念

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。

语法

类型& 引用变量名(对象名) = 引用实体;

示例 

很显然,在下面这个例子中,a与b共用同一地址。 

这里需要注意:引用类型必须和引用实体是同种类型的

1.2 引用特性

1. 引用在定义时必须初始化
2. 一个变量可以有多个引用
3. 引用一旦引用一个实体,再不能引用其他实体

示例 

引用定义时必须初始化。 

一个变量可以多次引用 

 引用一旦引用一个实体,再不能引用其他实体

1.3 常引用

1.权限只能缩小,不能放大。

2.类型转换时会产生临时变量,临时变量具有常性 

 关于这两个概念,我们结合代码来看,详见代码注释

所谓权限,无非就是对对象的操作权限,对常量我们的操作权限为只读,对变量则可读可写。 

那么类型转换时会产生临时变量是什么意思呢?

我们来看这一段代码:

int main()
{double a = 13.14;int b = a;//double转换为intint i = 97;char ch = 'a';if (i == ch) //char转换为int{cout << "相等" << endl;}cout << b << endl;return 0;
}

这一段代码有两个类型转换的例子,两者相类似,都是在类型转换时产生一个临时变量。

double a = 13.14;  int b = a;中,产生一个值为13的临时变量赋值给b。

i与ch的比较中,产生一个值为该字符ascll对应值的整型临时变量。

这些临时变量有一个共性,那就是具有常性。 

1.4  关于引用的使用场景

1.做参数

2.做返回值

1.做参数

我们以下述代码为例,曾经的交换数据,我们需要借助指针来实现,而现在引用就可以,而且还比指针简单很多。

引用版:
void Swap(int& x, int& y)
{int temp = x;x = y;y = temp;
}int main()
{int a = 10;int b = 20;cout << "a:" << a << "\t" << "b:" << b << endl;Swap(a, b);cout << "a:" << a << "\t" << "b:" << b << endl;return 0;
}
指针版: 

 

明显引用更为方便简洁。

2.做返回值

下面这段代码,大家觉得有没有问题呢?

int& add(int x, int y)
{int c = x + y;return c;
}
int main()
{int a = 10;int b = 5;int c = 9;int d = 10;int ret = add(a, b);cout << "ret:\t" << ret << endl;cout << "ret:\t" << ret << endl;return 0;
}

我们看看运行结果: 

很好,貌似没有问题,但我们发现,编译器给我们发出了一个小小的警告,如果是以前我们可能会嗤之以鼻不管不顾,但现在的我们不一样了,一个小小的警告也要抹杀在牢笼里。

完蛋,当我们准备解决警告时,却发现他是一个大问题。

这个问题我们之前遇到过,费了很大的力气才解决掉,现在他又出来了。

这是为什么呢?

很简单,一个函数的生命周期很短,函数调用,产生函数栈帧;函数调用结束,函数栈帧销毁。 那函数内产生局部变量或临时变量的生命周期自然随之结束,这一段空间就还给了操作系统,而我们直接对局部变量起别名并返回,然后在其他地方一直使用,不就相当于一直在退了房的宾馆里转悠嘛,违法行为不可取。

大家不爱看字,那就画个图给大家看。 

 如果你的东西还放在里面,宾馆换了个把锁,你进不去了,东西就丢了。

所以如果是全局变量,staic修饰过的变量,或者动态开辟的内存就不受限制。

1.5 传值,传引用效率比较

我们使用如下代码进行比较两种效率。 ( 关于clock () 的用法大家可以在网上查阅 )

struct A
{int arr[10000];
};void TestTranVal(A a)//传值
{
}void TestTranQuote(A& a)//传引用
{
}
int main()
{A a;size_t begin1 = clock();for(int i=0;i<10000;i++)TestTranVal(a);size_t end1 = clock();size_t begin2 = clock();for (int i = 0; i < 10000; i++)TestTranQuote(a);size_t end2 = clock();cout << "TestTranVal--time:\t" << end1 - begin1 << endl;cout << "TestTranQuote--time:\t" << end2 - begin2 << endl;return 0;
}

 

至于为什么会这样?且看下面这段文字!

以值作为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值类型,效率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低。 

1.6值和引用的作为返回值类型的性能比较
 

这里只需要将上面的代码略微改变。

struct A
{int arr[10000];
};A a;//全局变量A TestTranVal()
{return a;
}A& TestTranQuote()
{return a;
}
int main()
{size_t begin1 = clock();for (int i = 0; i < 10000; i++)TestTranVal();size_t end1 = clock();size_t begin2 = clock();for (int i = 0; i < 10000; i++)TestTranQuote();size_t end2 = clock();cout << "TestTranVal--time:\t" << end1 - begin1 << endl;cout << "TestTranQuote--time:\t" << end2 - begin2 << endl;return 0;
}

 

 造成这一现象的原因在1.5后面哦!

1.7引用和指针的区别

相信大家在学习引用的时候,总是有一种似曾相识的感觉,这是因为他的功能和指针有很大部分的重叠。

在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。

但在底层实现上实际是有空间的,因为引用是按照指针方式来实现的。

int main()
{int a = 10;int c = 9;int& b = a;b = 20;cout << " a " << a << endl;int* p = &a;*p = 30;cout << " a " << a << endl;p = &c;cout << " *p " << *p << endl;return 0;
}

我们来看看汇编视角的引用与指针:

 很显然,在汇编看来,指针与引用并没有区别。

我们试着来总结一下指针与引用的不同点

1.引用是给一个变量起别名,而指针存储变量的数据地址。

2.引用在定义时必须初始化,指针则没有这个要求。

3.引用定义后就不能再更改指向,指针可以,这是他们两个最本质的区别,也是引用无法完全替代指针的根本原因。

 4.在sizeof中,引用的结果就是引用类型的大小,而指针恒定为4或者8(取决于编译器)。

5.引用相对于指针更加安全,没有空引用,但有空指针。

6.譬如自增自减,引用操作的是对象的实体内容,而指针操作的是地址块。

7.在底层汇编视角,引用与指针并没有什么区别。

8.对于对象的访问方式不同,指针需要解引用,而引用由编译器处理。

2.  内联函数

2.1 概念 

以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调
用建立栈帧的开销,内联函数提升程序运行的效率。


如果在上述函数前增加inline关键字将其改成内联函数,在编译期间编译器会用函数体替换函数的
调用。

 2.2 内联函数的特性

1. inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会
用函数体替换函数调用,缺陷:可能会使目标文件变大,优势:少了调用开销,提高程序运
行效率。
2. inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同,一般建
议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不
是递归、且频繁调用的函数采用inline修饰,否则编译器会忽略inline特性
3. inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址
了,链接就会找不到

2.3 内联函数与宏

宏的优缺点? 

优点:
1.增强代码的复用性。
2.提高性能。
缺点:
1.不方便调试宏。(因为预编译阶段进行了替换)
2.导致代码可读性差,可维护性差,容易误用。
3.没有类型安全的检查 。

C++有哪些技术替代宏?
 

1. 常量定义 换用const enum
2. 短小函数定义 换用内联函数 

结语 

    指舞键盘上,悠然博弈回。如果您感兴趣,不妨看看我其他的文章,也许会有更多的收获。希望我们能在未来的日子里一起成长,共同进步。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/659819.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

stm32--simulink开发之--timer的学习,硬件输入中断,触发事件

总体的参考链接是&#xff1a; https://ww2.mathworks.cn/help/ecoder/stmicroelectronicsstm32f4discovery/ref/timer.html 输入&#xff1a; 1&#xff0c;配置项&#xff1a;Enable frequency input 缩写&#xff1a;freq conunt 说明&#xff1a;“freq count — Frequency…

2024热门游泳耳机排行榜,精选四款游泳耳机品牌

在追求健康生活的今天&#xff0c;游泳成为了许多人健身的首选活动之一。而为了让游泳体验更加愉悦&#xff0c;选择一款适合的游泳耳机显得尤为重要。这不仅能够为游泳者提供动感的音乐&#xff0c;缓解游泳过程中的疲劳感&#xff0c;同时还有助于提高游泳效率。在市场上琳琅…

中文计算机自学指南:打开全栈开发之门 | 开源日报 No.161

PKUFlyingPig/cs-self-learning Stars: 40.3k License: MIT cs-self-learning 是一个计算机自学指南。 该项目旨在提供一本完整的计算机自学指南&#xff0c;帮助初学者通过优质资源快速成长为全能程序员。 主要功能和核心优势包括&#xff1a; 提供丰富的开源课程资源支持多…

案例三:U盘提示格式化?3种方法帮你拯救它

在U盘的使用过程中最尴尬的情况就是遇到“无法打开&#xff0c;需要进行格式化”的提示。此时&#xff0c;我们如何才能在不破坏内部数据的情况下&#xff0c;挽救这个U盘呢&#xff1f; 小编今天就和说3个方法&#xff0c;可以用来解决U盘“无法打开&#xff0c;需要进行格式化…

工作流框架Activiti

工作流框架activiti 实现入住管理&#xff0c;审批流。 实现入退住&#xff0c;涉及多个表单的提交和多个角色的审核&#xff0c;若要实现这些流程的开发&#xff0c;最好的技术选型是使用工作流技术。 工作流(Work Flow)&#xff1a;是一项将系统任务或操作抽取&#xff0c…

Windows10更新失败 错误 0x80070643、KB5034441的解决方法之二

Windows10更新失败 错误 0x80070643、KB5034441 在知乎Windows10更新失败 错误 0x80070643、KB5034441的原因分析和几个解决方法 - 知乎 参考文章进行操作&#xff0c;更详细信息自己看上面链接。 我电脑的硬盘是mbr格式&#xff0c;而且没有划分恢复分区。 Microsoft Windo…

nop-entropy可逆计算入门(1)

第1步&#xff1a;从大佬的gitee&#xff1a;https://gitee.com/canonical-entropy/nop-entropy下载源码&#xff0c;进行本地编译&#xff0c;具体编译看项目下的readme,想偷懒的可以下载我编译后的jar&#xff0c;放到自己的maven仓库 https://pan.baidu.com/s/15qANnrCh5RV…

Node.js的学习1

Node.js简介 浏览器是JavaScript的前端运行环境Node.js是JavaScript的后端运行环境Node.js中无法调用DOM和BOM等浏览器内置API 终端中的快捷键 使用向上箭头&#xff0c;可以快速定位到上一次执行的命令使用tab键&#xff0c;可以快速补全路径使用esc键&#xff0c;可以快速清…

Sentinel 知识总结

Sentinel 知识总结 Sentinel 是阿里巴巴开源的一个轻量级流量控制框架&#xff0c;主要用于保护系统稳定性和流畅性。它提供了多种流量控制策略&#xff0c;包括QPS限流、并发数限流、线程池限流等&#xff0c;并且支持集群限流。此外&#xff0c;Sentinel还提供了熔断降级、系…

学习使用vite+vue3的所遇问题总结

组件中使用<script>标签忘记加 setup 这会导致Navbar 没有暴露出来&#xff0c;导致使用不了&#xff0c;出现以下报错 这是因为&#xff0c;如果不用setup&#xff0c;就得使用 export default …… setup 是后者的语法糖 在Vue.js中&#xff0c;你可以通过route对象…

USTC ICS(2023Fall) Lab5 Password Verification

LC-3汇编语言 .orig x3000 LOOP1 AND R1,R1,#0ADD R1,R1,#3LEA R0, string1PUTS ;打印string1AND R0,R0,#0ADD R0, R0, #10 OUT ;打印换行符GETCOUT;检查输入的字符是否为W(ASCII码为87)ADD R0,R0,#-16ADD R0,R0,#-16ADD R0,R0,#-16ADD R…

H5网站在线客服小程序源码系统,完全开源可二开 带完整的安装代码包以及搭建教程

互联网的快速发展&#xff0c;H5网站已成为企业与客户沟通的重要渠道。然而&#xff0c;许多H5网站在客户服务方面存在不足&#xff0c;无法及时响应客户的问题和需求。小编给大家分享了一款H5网站在线客服小程序源码系统&#xff0c;旨在为企业提供完善的客户服务解决方案。 …

(自用)learnOpenGL学习总结-高级OpenGL-几何着色器

在顶点着色器和片段着色器中间还有一个几何着色器。 几何着色器的输入是一个图元的一组顶点&#xff0c;在几何着色器中进行任意变换之后再给片段着色器&#xff0c;可以变成完全不一样的图元、可以生成更多的顶点。 #version 330 core layout (points) in; layout (line_str…

案例四:误Ghost分区恢复

1、案例 小王电脑最近有点问题&#xff0c;于是打算将电脑系统重装系统&#xff0c;原本5个分区&#xff0c;第一个区是操作系统区&#xff0c;后4个用户数据区&#xff0c;在一次GHOST时失误&#xff0c;做完发现硬盘只有一个系统区&#xff0c;两个数据区消失了&#xff0c;…

右手螺旋线定则

通电螺线管中的安培定则&#xff08;安培定则二&#xff09;&#xff1a;用右手握住通电螺线管&#xff0c;让四指指向电流的方向&#xff0c;那么大拇指所指的那一端是通电螺线管的N极。

Redis核心技术与实战【学习笔记】 - 9.如何避免单线程模型的阻塞

概述 Redis 被广泛应用的原因是因为它支持高性能访问。所以&#xff0c;我们要重视所有可能影响 Redis 性能的因素&#xff08;如命令操作、系统配置、关键机制、硬件配置等&#xff09;。 影响 Redis 性能的 5 大方面的潜在因素分别是&#xff1a; Redis 内部的阻塞式操作C…

OpenAI、斯坦福大学提出Meta-Prompting,有效提升语言模型的性能

为了研究如何提高语言模型的性能&#xff0c;使其更充分有效地输出对于提问的回答&#xff0c;来自斯坦福和 OpenAI 的学者强强联手&#xff0c;通过提出一种名为元提示&#xff08;meta-prompting&#xff09;的方法来深入探索。元提示通过让单个语言模型&#xff08;如 GPT-4…

2023.1.31 关于 Redis 分布式锁详解

目录 引言 分布式锁 引入分布式锁 引入 set nx 引入过期时间 引入校验机制 引入 lua 脚本 引入过期时间续约&#xff08;看门狗&#xff09; 引入 redlock 算法 结语 引言 在一个分布式系统中&#xff0c;可能会涉及到多个节点访问同一个公共资源的情况此时就需要通过…

代码随想录算法训练营第五十一天|714.买卖股票的最佳时机含手续费、309.最佳买卖股票时机含冷冻期、股票问题总结、最长上升子序列

题目&#xff1a;714.买卖股票的最佳时机含手续费 文章链接&#xff1a;代码随想录 视频链接&#xff1a;LeetCode:714.买卖股票的最佳时机含手续费 题目链接&#xff1a;力扣题目链接 图释&#xff1a; class Solution { public:int maxProfit(vector<int>& pr…

C# Onnx yolov8 仪表指针检测

目录 效果 模型信息 项目 代码 训练数据 下载 C# Onnx yolov8 仪表指针检测 效果 模型信息 Model Properties ------------------------- date&#xff1a;2024-01-31T11:19:38.828556 author&#xff1a;Ultralytics task&#xff1a;detect license&#xff1a;AGPL-…