【C++奇遇记】函数探幽(上)

news2024/9/22 7:06:49

🎬 博客主页:博主链接
🎥 本文由 M malloc 原创,首发于 CSDN🙉
🎄 学习专栏推荐:LeetCode刷题集 数据库专栏 初阶数据结构
🏅 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
📆 未来很长,值得我们全力奔赴更美好的生活✨

在这里插入图片描述
在这里插入图片描述

文章目录

  • 😇内联函数的前情介绍
    • 📝任何时候我们都要用内联函数吗?
    • 😇内联与宏
  • 😇引用变量
    • 📝创建引用变量
    • ✉将引用用作函数参数
    • 📋利用引用和指针来实现swap()函数
  • 📃如何巩固学习
  • 📃本文小结

😇内联函数的前情介绍

😁内联函数是c++为提高程序运行速度所做的一项改进。常规函数和内联函数之间的主要区别不在于编写方式,而在于c++编译器如何将它们组合到程序中。要了解内联函数与常规函数之间的区别,必须深入到程序内部。


编译过程的最终产品是可执行程序

它们由一组机器语言指令组成。运行程序时,操作系统将这些指令载入到计算机内存中,因此每条指令都有特定的内存地址。计算机随后将逐步执行这些指令。有时(如有循环或分支语句时),将跳过一些指令,向前或向后跳到特定地址。常规函数调用也使程序跳到另一个地址(函数的地址),并在函数结束时返回。


📝任何时候我们都要用内联函数吗?

我们应该选择地使用内联函数。如果执行函数代码的时间比处理函数调用机制的时间长,则节省的时间将只占整个过程的很小一部分。如果代码执行时间很短,则内联调用就可以节省非内联调用使用的大部分时间。另一方面,由于这个过程相当快美因茨尽管节省了该过程的大部分时间,但节省的时间绝对值并不大,除非该函数经常被调用。


使用内联函数特性

  1. 在函数声明前加上关键字inline;
  2. 在函数定义前加上关键字inline。

通常的做法时省略原型,将整个定义(即函数头和所有函数代码)放在本应提供原型的地方。

📝程序员请求将函数作为内联函数时,编译器并不一定会满足这种要求。他可能认为该函数过大或注意到函数调用了自己(内联函数不能递归),因此不将其作为内联函数;而有些编译器没有启用或实现这种特性。


实例

通过内联函数square()演示了内联技术。注意到整个函数定义都放在一行中,但并不一定非得这样做。然而,如果函数定义占用多行(假定没有使用冗长的标识符),则将其作为内联函数就不太合适。

#include<iostream>
using namespace std;

inline double square(double x)
{
	return x * x;
}

int main()
{
	double a, b;
	double c = 13.0;
	a = square(5.0);
	b = square(4.5 + 7.5);
	cout << "a = " << a << ", b = " << b << "\n";
	cout << "c = " << c; 
	cout << ", c squared = " << square(c++) << "\n";
	cout << "Now c = " << c << "\n";
	return 0;
}

输出
在这里插入图片描述

📋输出表明,内联函数和常规函数一样,也是按值来传递参数的。如果参数为表达式,如4.5+7.5,则函数将传递表达式的值(这里为12)。这使得c++的内联功能远远胜过c语言的宏定义。

😇内联与宏

🐤宏的优缺点:

优点:

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

c++中那些技术替换宏?

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

😇引用变量

c++新增了一种复合类型—引用变量

引用是已定义的变量的别名(另一个名称)。

📝创建引用变量

前言

在c和c++使用&符号来指示变量的地址。c++给&符号赋予了另一个含义,将其用来声明引用。例如,要将rodents作为rats变量的别名,可以这样做:

int rats;
int& rodents = rats;

其中,&不是地址运算符,而是类型标识符的一部分。就像声明中的char* 指的是指向char的指针一样,int&指的是指向int的引用


C语言的用户

📝首次接触到引用时可能也会有些疑惑,因为这些用户很自然地会想到指针,但它们之间还是有区别的。例如,可以创建指向rats的引用和指针:

int rats = 101;
int& rodents = rats;
int* prats = &rats;

引用的特点

必须在引用时将其初始化,而不能像指针那样,先声明,再赋值:我们来看下述代码

int main()
{
	int rat;
	int& rodents;
	rodents = rat;
	return 0;
}

报错信息
在这里插入图片描述
注意

必须在声明引用变量时进行初始化。


C++关于全局变量和局部变量的规定定义了一种名称空间层次。每个声明区域都可以声明名称,这些名称独立于在其他声明区域中声明的名称。在一个函数中声明的局部变量不会与在另一个函数中声明的局部变量发生冲突。

#include<iostream>
using namespace std;
int add(int left, int right)
{
	return left + right;
}
double add(double left, double right)
{
	return left + right;
}
void Swap(int* p1, int* p2)
{}
void Swap(double* p1, double* p2)
{}

int main()
{
	cout << add(1, 1) << endl;
	cout << add(1.1, 1.1) << endl;

	return 0;
}

在上述代码中从#include 到最后一个有括号为止都属于声明区(全局名称空间)

✉将引用用作函数参数

引用经常被用作函数参数,使得函数中的变量名成为调用程序中的变量名的别名。这种传递参数的方法成为按引用传递。按引用传递允许被调用的函数能够访问调用函数中的变量。


按值传递

void test(int x)
{

}

int main()
{
	int rat;
	test(rat);
	return 0;
}

两个变量,两个名称

按引用传递

void test(int& x)
{

}

int main()
{
	int rat;
	test(rat);
	return 0;
}

一个变量。两个名称

📋利用引用和指针来实现swap()函数

💐在常见的日常刷题的过程中,我们经常要交换两个变量的值,这里我们对使用引用和使用指针做一下比较。

引用实现swap()函数

#include<iostream>
using namespace std;
void swapy(int& x, int& y)
{
	int temp = x;
	x = y;
	y = temp;
}
int main()
{
	int x = 1, y = 0;
	cout << "x = " << x << "y = " << y << endl;
	swapy(x, y);
	cout << "x = " << x << "y = " << y << endl;

	return 0;
}

在这里插入图片描述

注意

为什么我们用引用可以实现呢?我们来分析一下,因为在这里我们用了引用作为函数的参数,他就相当于我们传递上来参数的别名,也就是换了个名字而已,所以我们修改的时候自然而然的也能进行交换


指针实现swap()函数

#include<iostream>
using namespace std;

void swapp(int* x, int* y)
{
	int temp = *x;
	*x = *y;
	*y = temp;
}
int main()
{
	int x = 1, y = 0;
	cout << "x = " << x << "y = " << y << endl;
	swapp(&x, &y);
	cout << "x = " << x << "y = " << y << endl;

	return 0;
}

📃如何巩固学习

提示:在学习的过程中,我们需要先自行进行思考,并且多去阅读一些大佬的书籍,俗话说的好,书籍是人类进步的阶梯!

📃本文小结

  1. C++鼓励程序员在开发程序时使用多个文件。一种有效的组织策略是,使用头文件来定义,为操纵用户类型的函数提供函数原型;并将函数定义放在一个独立的源代码文件中。头文件和源代码文件一起定义和实现了用户定义的类型及其使用方式。最后,将main()和其他使用这些函数的函数放在第三个文件中。

好啦今日的分享到这里就结束啦,我是爱你们的M malloc希望可以帮助到你们噢,最后别忘记三连啦!!

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

操作系统 - 小记 230803

文章目录 计算机的硬件组成程序的存储和执行程序语言的设计和进化存储设备的层次结构操作系统 https://www.bilibili.com/video/BV1Q5411w7z5?p2 计算机的硬件组成 CPU CU&#xff0c;控制单元ALU&#xff0c;算数逻辑单元寄存器 IO Bridge 处理器和外部交互的桥梁Main Memory…

redis原理 4:雷厉风行 —— 管道

大多数同学一直以来对 Redis 管道有一个误解&#xff0c;他们以为这是 Redis 服务器提供的一种特别的技术&#xff0c;有了这种技术就可以加速 Redis 的存取效率。但是实际上 Redis 管道 (Pipeline) 本身并不是 Redis 服务器直接提供的技术&#xff0c;这个技术本质上是由客户端…

【LeetCode-简单】剑指 Offer 22. 链表中倒数第k个节点(详解)

题目 输入一个链表&#xff0c;输出该链表中倒数第k个节点。为了符合大多数人的习惯&#xff0c;本题从1开始计数&#xff0c;即链表的尾节点是倒数第1个节点。 例如&#xff0c;一个链表有 6 个节点&#xff0c;从头节点开始&#xff0c;它们的值依次是 1、2、3、4、5、6。这…

2024年杭电MBA项目招生信息全面了解

2024年全国管理类硕士联考备考已经到了最火热的阶段&#xff0c;不少考生开始持续将注意力集中在备考的规划中&#xff01;杭州达立易考教育整合浙江省内的MBA项目信息&#xff0c;为大家详细梳理了相关报考参考内容&#xff0c;方便大家更好完成择校以及针对性的备考工作。本期…

差异对比犀利手册:使用 Partial Diff 插件在 VSCode 中比较代码差异

简介&#xff1a; 在本教程中&#xff0c;我们将介绍如何在 Visual Studio Code&#xff08;VSCode&#xff09;编辑器中安装和使用 Partial Diff 插件来进行源代码文件的差异比较。Partial Diff 插件是一个强大且简单的工具&#xff0c;可以帮助你更容易地查看和理解代码的变…

14.2.2 【Linux】software, hardware RAID

磁盘阵列分为硬件与软件。所谓的硬件磁盘阵列是通过磁盘阵列卡来达成阵列的目的。磁盘阵列卡上面有一块专门的芯片在处理 RAID 的任务&#xff0c;因此在性能方面会比较好。在很多任务 &#xff08;例如 RAID 5 的同位检查码计算&#xff09; 磁盘阵列并不会重复消耗原本系统的…

“已停止访问该网页“ 解决流程,微信外部链接内容管理规范

登录手机管家官网 腾讯安全-网址安全中心 自行处理。 说明&#xff1a; 一直以来&#xff0c;微信致力于为用户提供绿色、健康的网络生态环境。 根据法律法规的规定&#xff0c;微信将落实“以安全为底线”的互联互通&#xff0c;为确保高质量的平台内容和良好的用户体验&a…

Multimodal Learning with Transformer: A Survey

Transformer多模态学习 Abstract1 INTRODUCTION2 BACKGROUND2.1 Multimodal Learning (MML)2.2 Transformers: a Brief History and Milestones2.3 Multimodal Big Data 3 TRANSFORMERS: A GEOMETRICALLY TOPOLOGICAL PERSPECTIVE3.1 Vanilla Transformer3.1.1 Input Tokenizat…

使用手机相机检测电脑屏幕刷新率Hz

使用手机相机检测电脑屏幕刷新率Hz 1、电脑打开https://www.testufo.com/frameskipping 2、相机专业模式&#xff1a;快门1/10、ISO自动&#xff0c;拍摄一张照片。120Hz至少要有12个亮块&#xff0c;50Hz至少有6个亮块。 更改刷新速率 1、选择 “开始>设置>系统>显示…

ARM64 常见汇编指令学习 10 -- 无符号位域提取指令 BFXIL

文章目录 BFXIL使用例子 BFXIL 有2种语法&#xff1a; BFXIL Wd, Wn, #lsb, #width ; 32-bit BFXIL Xd, Xn, #lsb, #width ; 64-bit从Wn 寄存器的第 lsb 位开始&#xff0c;提取 width 位&#xff0c;替换 Wd 寄存器的最低 width位&#xff0c;剩余高位不改变。 使用例子 假…

科技云报道:向量数据库:AI时代的下一个热点

科技云报道原创。 最近&#xff0c;又一个概念火了——向量数据库。 随着大模型带来的应用需求提升&#xff0c;4月以来多家海外知名向量数据库创业企业传出融资喜讯。 4月28日&#xff0c;向量数据库平台Pinecone宣布获得1亿美元&#xff08;约7亿元&#xff09;B轮融资&am…

DBeaver连MySQL库报错public key retrieval is not allowed

连接报错: public key retrieval is not allowed解决办法&#xff1a; 右击你连接的库进行编辑连接&#xff08;或者直接按F4打开编辑&#xff09; 然后点击驱动属性里面进行设置 找到allowPublicKeyRetrieval属性&#xff0c;把值由false改为true 注&#xff1a;连接成功后如…

Flutter 混合架构方案探索

得益于 Flutter 优秀的跨平台表现&#xff0c;混合开发在如今的 App 中随处可见&#xff0c;如最近微信公布的小程序新渲染引擎 Skyline 发布正式版也在底层渲染上使用了 Flutter&#xff0c;号称渲染速度提升50%。 在现有的原生 App 中引入 Flutter 来开发不是一件简单的事&a…

Kubernetes高可用集群二进制部署(四)部署kubectl和kube-controller-manager、kube-scheduler

Kubernetes概述 使用kubeadm快速部署一个k8s集群 Kubernetes高可用集群二进制部署&#xff08;一&#xff09;主机准备和负载均衡器安装 Kubernetes高可用集群二进制部署&#xff08;二&#xff09;ETCD集群部署 Kubernetes高可用集群二进制部署&#xff08;三&#xff09;部署…

解密爬虫ip是如何被识别屏蔽的

在当今信息化的时代&#xff0c;网络爬虫已经成为许多企业、学术机构和个人不可或缺的工具。然而&#xff0c;随着网站安全防护的升级&#xff0c;爬虫ip往往容易被识别并屏蔽&#xff0c;给爬虫工作增加了许多困扰。在这里&#xff0c;作为一家专业的爬虫ip供应商&#xff0c;…

一文了解MySQL中的多版本并发控制作者

最近在阅读《认知觉醒》这本书&#xff0c;里面有句话非常打动我&#xff1a;通过自己的语言&#xff0c;用最简单的话把一件事情讲清楚&#xff0c;最好让外行人也能听懂。 也许这就是大道至简&#xff0c;只是我们习惯了烦琐和复杂。 希望借助今天这篇文章&#xff0c;能用…

关于DC电源模块的噪音问题

BOSHIDA 关于DC电源模块的噪音问题 BOSHIDA DC电源模块是广泛使用的电源模块&#xff0c;它在各个领域中都有应用&#xff0c;例如&#xff1a;电子设备、计算机、通讯等领域。然而&#xff0c;DC电源模块也存在一些噪音问题&#xff0c;这些噪音问题会影响到电子设备的正常运…

SW - 装配图用的组合零件的制作步骤

文章目录 SW - 装配图用的组合零件的制作步骤概述笔记END SW - 装配图用的组合零件的制作步骤 概述 一套相关零件做好后, 需要做装配体, 将零件都装上, 看看是否有纰漏. 如果不做总装图, 真不放心. 万一废了, 耽误的时间大把的. 做总装图的时间比做零件的2个星期比起来, 代价…

C语言进阶——sprintf与sscanf、文件的随机读写(fseek、ftell、rewind)

目录 sprintf与sscanf sprintf sscanf 文件的随机读写 fseek ftell rewind sprintf与sscanf 与之前学习过的进行对比&#xff1a; scanf 是针对标准输入的格式化输入语句 printf 是针对标准输出的格式化输出语句 fscanf 是针对所有输入流的格式化语句 fprintf 是针对所…

深度学习Redis(1):Redis内存模型

前言 Redis是目前最火爆的内存数据库之一&#xff0c;通过在内存中读写数据&#xff0c;大大提高了读写速度&#xff0c;可以说Redis是实现网站高并发不可或缺的一部分。 我们使用Redis时&#xff0c;会接触Redis的5种对象类型&#xff08;字符串、哈希、列表、集合、有序集合…