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

🎬 博客主页:博主链接

🎥 本文由 M malloc 原创,首发于 CSDN🙉

🎄 学习专栏推荐:LeetCode刷题集 数据库专栏 初阶数据结构

🏅 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!

📆 未来很长,值得我们全力奔赴更美好的生活✨


文章目录

😇内联函数的前情介绍

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


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

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


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

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


使用内联函数特性

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

通常的做法时省略原型,将整个定义(即函数头和所有函数代码)放在本应提供原型的地方。
📝程序员请求将函数作为内联函数时,编译器并不一定会满足这种要求。他可能认为该函数过大或注意到函数调用了自己(内联函数不能递归),因此不将其作为内联函数;而有些编译器没有启用或实现这种特性。


实例

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

c++ 复制代码
#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变量的别名,可以这样做:

c++ 复制代码
int rats;
int& rodents = rats;

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


C语言的用户

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

c++ 复制代码
int rats = 101;
int& rodents = rats;
int* prats = &rats;

引用的特点

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

c++ 复制代码
int main()
{
	int rat;
	int& rodents;
	rodents = rat;
	return 0;
}

报错信息

注意

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


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

cpp 复制代码
#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 到最后一个有括号为止都属于声明区(全局名称空间)

✉将引用用作函数参数

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


按值传递

c++ 复制代码
void test(int x)
{

}

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

两个变量,两个名称

按引用传递

c++ 复制代码
void test(int& x)
{

}

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

一个变量。两个名称

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

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

引用实现swap()函数

c++ 复制代码
#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()函数

c++ 复制代码
#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希望可以帮助到你们噢,最后别忘记三连啦!!

相关推荐
IT女孩儿20 分钟前
JavaScript--WebAPI查缺补漏(二)
开发语言·前端·javascript·html·ecmascript
m0_7482389221 分钟前
webgis入门实战案例——智慧校园
开发语言·ios·swift
悲伤小伞26 分钟前
C++_数据结构_详解二叉搜索树
c语言·数据结构·c++·笔记·算法
Clockwiseee35 分钟前
PHP伪协议总结
android·开发语言·php
小灰灰搞电子36 分钟前
Qt实现Android的图案密码(图形解锁)源码分享
开发语言·qt
m0_675988231 小时前
Leetcode3218. 切蛋糕的最小总开销 I
c++·算法·leetcode·职场和发展
吴冰_hogan2 小时前
JVM(Java虚拟机)的组成部分详解
java·开发语言·jvm
白宇横流学长3 小时前
基于java出租车计价器设计与实现【源码+文档+部署讲解】
java·开发语言
数据小爬虫@5 小时前
Java爬虫实战:深度解析Lazada商品详情
java·开发语言
songroom5 小时前
Rust: offset祼指针操作
开发语言·算法·rust