【C++】内联函数与快速读入read函数(整型)

news/2024/7/24 6:51:17 标签: c语言, 开发语言, c++, 学习

前言

学习C++的过程中,在很多的题解中都发现了利用read来实现快速读入的功能,今天,我们就来学习一下快速读入这个函数,并顺带着学习一下内联函数

内联函数

学习read函数之前,我们先来学习一下内联函数

引入

我们都知道,函数在分类上可以分为主调函数和被调函数,main函数就是主调函数,是调用其他函数的函数,在C程序中mian函数就是主调函数
而像bubble_sort这些其他的函数就称为被调函数,他们都被主调函数调用

在程序执行的时候,都是先执行主调函数再执行被调函数,而当程序在执行被调函数,主调函数是停止的、不执行的,(此处可以借助调试时,按ctrl + fn + F11进入被调函数内部 来进行理解),当执行完被调函数,程序再继续执行刚才主调函数中停止时后面的部分,

我们都知道,函数调用是需要做一些准备的,
首先,程序要在栈中开辟出足够大的空间,先将实参、局部变量、返回地址以及若干寄存器都存储在其中,
然后,才能执行函数体中的代码
最后,函数体中的代码执行完毕后还要清理现场,也就是释放内存将之前压入栈中的数据都出栈,才能接着执行函数调用位置以后的代码。

此处可以参考我的另一篇文章函数栈帧的创建和销毁,可能会有助于理解函数调用的过程

经过上面的介绍,相信大家可以理解一件事:
函数体很庞大时,其准备所需的时间就可以忽略不计
而当函数体只有一两条语句时,其准备所需的时间就不可忽略,一旦这个简单的函数要调用很多次,那在时间上和空间上都是一种浪费

此时,人们就想,能不能设计一种函数,当它结束调用时不释放它在内存中开辟的空间,此时,就出现了内联函数

定义

为了消除函数调用的时空开销,也就是更快速
C++ 中提供一种提高效率的方法,即在编译时将函数调用处用函数体替换
类似于C语言中的宏展开。
这种在函数调用处直接嵌入函数体的函数称为内联函数(Inline Function),又称内嵌函数或者内置函数

使用

下面,通过一个简单的例子来介绍内敛函数如何使用

例子

使用内联函数创建一个函数,功能是交换两个数

#include<iostream>

using namespace std;

inline void swap(int* a, int* b)
{
	int tmp = *b;
	*b = *a;
	*a = tmp;
}

int main()
{
	int a = 1;
	int b = 2;
	cout << a << endl << b << endl;
	swap(&a, &b);
	cout << a << endl << b << endl;

	return 0;
}

使用内联函数,需要在函数定义的开头使用inline关键字

注意

函数声明处写inline是无意义的,编译器会自动忽略掉他

内联函数的使用情况

因为在函数调用完成后,不会销毁它在内存中开辟的空间
所以,实际上编译后的程序中是存在着多份相同的内容拷贝

所以,当内联函数的函数体很大时,编译后的程序也非常大
所以再次强调,一般只将那些短小的、频繁调用的函数声明为内联函数

内联函数与宏定义

宏定义的函数不仅存在运算优先级的问题,并且也不可调试

相较于宏定义的直接替换,内联机制既具备宏代码的效率,又增加了安全性,而且可以自由操作的类的数据成员,所以应该尽量使用内联函数来取代宏代码

read函数

学习完了内联函数,接下来我们来学习快速读入:read函数

基本思路

读取字符

既然是读取数据,并且是一个一个的读取,那么我们肯定会用到getchar来读取字符

设置条件

其次,我们对于要输入的数据肯定是有一定的要求的,不能什么数据都传输进来,
所以我们就要都传入的数据进行判断,看其是否满足我们的条件

代码实现

下面,我们提供两种实现方法

简单版本

inline long long read()
{
	char cc = getchar();//读取第一个字符
	long long f = 1;//f用于判断符号正负
	long long ans = 0;//ans用于控制数字

	while (cc < '0' || cc>'9')
	{
		if (cc == '-')
		{
			f = -1;
		}
		cc = getchar();
	}

	while (cc >= '0' && cc <= '9')//遇到空格,则这个整形数据读取结束
	{
		ans = (ans * 10) + (cc - '0');
		cc = getchar();
	}

	return f * ans;
}

优化版本

当然,我们也可以通过位运算来优化上面这个解法,毕竟而我们都知道位运算比乘除法的运行速率要快

inline long long read()
{
	char cc = getchar();
	long long f = 1;
	long long ans = 0;
	while (cc < '0' || cc>'9')
	{
		if (cc == '-')
		{
			f = -1;
		}
		cc = getchar();
	}

	while (cc >= '0' && cc <= '9')
	{
		ans = (ans << 1) + (ans << 3) + (cc - '0');//向右移动一位是乘以2
		cc = getchar();
	}

	return f * ans;
}

练习题

下面,还是给出一道练习题,方便大家理解

题目:A+B problem

题目描述:输入一个正整数n,表示有n个数,接下来再输入n个数。计算它们的和。

样例输入:

20 233 222 2334 123 654 2345 235 2345 321 357 123 45 65 346 76 456 778
-123 -20 -1000

样例输出:

9915

示例代码

#include<cstdio>
#include<iostream>

using namespace std;

inline long long read()
{
	char cc = getchar();
	long long f = 1;
	long long ans = 0;
	while (cc < '0' || cc>'9')
	{
		if (cc == '-')
		{
			f = -1;
		}
		cc = getchar();
	}

	while (cc >= '0' && cc <= '9')
	{
		ans = (ans << 1) + (ans << 3) + (cc - '0');
		cc = getchar();
	}

	return f * ans;
}

int main()
{
	long long ans = 0;
	int n = read();
	int a = 0;
	for (int i = 0; i < n; i++)
	{
		a = read();
		ans += a;
	}
	cout << ans << endl;

	return 0;
}

结语

好的,关于内联函数和read函数的介绍和学习到这里就结束了,希望对你有帮助,我们下篇文章见~


http://www.niftyadmin.cn/n/4993069.html

相关文章

SpringBoot2.0集成WebSocket,多客户端

适用于单客户端&#xff0c;一个账号登陆一个客户端&#xff0c;登陆多个客户端会报错 The remote endpoint was in state [TEXT_FULL_WRITING] 这是因为此时的session是不同的&#xff0c;只能锁住一个session&#xff0c;解决此问题的方法把全局静态对象锁住&#xff0c;因…

【Datawhale】AI夏令营第三期——基于论文摘要的文本分类笔记(下)

笔记上部分请看【Datawhale】AI夏令营第三期——基于论文摘要的文本分类笔记(上) 文章目录 一、深度学习Topline1.1 数据预处理1.2 模型训练1.3 评估模型1.4 测试集推理1.5 后续改进 二、大模型Topline2.1 大模型介绍2.2 大模型是什么&#xff1f;2.3 大模型的原理2.4 大模型可…

【Cadence】Calculator计算sp的3dB带宽

【Cadence】Calculator计算sp的3dB带宽 1.计算最大增益2.cross函数3. 3dB带宽 下面演示如何在Cadence计算s参数&#xff08;如增益&#xff09;的3dB带宽 1.计算最大增益 ymax函数 2.cross函数 cross函数可以计算经过y轴给定值对应的x坐标 edge number选择1是经过的第一个点…

9.嵌套路由

1.添加主路由main <template><div><!-- 页面布局 --><el-container><!-- 侧边栏 --><el-aside width"200px">Aside</el-aside><!-- 页面布局 右边 包括header 和main --><el-container><el-header>Head…

git 忽略已经提交的文件或文件夹 (修改.gitignore文件无效)

场景描述&#xff1a;项目开发到一半&#xff0c;追加了模块&#xff0c;提交的时候未注意将不需要提交的文件或者目录提交到.gitignore&#xff0c;然后提交后发现再修改git配置文件已无法阻拦更新&#xff0c;查阅官方资料&#xff1a; 核心点&#xff1a;.gitignore 之前&a…

结合OB Cloud区别于MySQL的4大特性,规划降本方案

任何一家企业想要获得持续性的发展与盈利&#xff0c;“降本增效”都是难以绕开的命题。但是“一刀切”的降本影响往往不太可控&#xff0c;成本的快速收缩往往会给业务带来低效运营和增长缓慢的风险。所以我们所说的降本&#xff0c;是指在成本降低的同时&#xff0c;效率不降…

IO进程线程、互斥锁、进程间通信:1、无名管道,2、有名管道

一、线程互斥 引入互斥(mutual exclusion)锁的目的是用来保证共享数据操作的完整性。 互斥锁主要用来保护临界资源 每个临界资源都由一个互斥锁来保护&#xff0c;任何时刻最多只能有一个线程能访问该资源 线程必须先获得互斥锁才能访问临界资源&#xff0c;访问完资源后释…

部署java程序的服务器cpu过高如何排查和解决

1.top命令找到占用CPU高的Java进程PID 2.根据进程ID找到占用CPU高的线程 ps -mp pid -o THREAD,tid | sort -r ps -mp 124682 -o THREAD,tid | sort -r 3.将指定的线程ID输出为16进制格式 printf “%x\n” tid printf "%x\n" 6384 18f0 4.jstack pid |…