8、C++函数

本文详细介绍了C++中的函数重载、名字修饰(Name Mangling)、函数指针、命名空间、内联函数以及递归的概念与应用。通过实例展示了如何使用函数指针实现回调函数,以及递归计算斐波那契数列的多种优化方法,包括尾递归和动态规划。同时,讨论了递归的优缺点及其优化策略。
摘要由CSDN通过智能技术生成

一、函数重载overload

  • 查看反汇编
#include <iostream>

using namespace std;

int test(int n)
{
	return n;
}

int test(double d)
{
	return (int)d;
}

int test(int n, double d)
{
	return n + d;
}

int main()
{
	int result = test(1);
	result = test(2.0);
	result = test(1, 2.0);
	return 0;
}

在这里插入图片描述

二、C++ Name Mangling

  • C++函数签名:使用undname工具查看
    • ①.打开项目下的.obj文件,我的路径:C:\DevelopProject\TestProject\ConsoleApplication1\ConsoleApplication1\Debug\ConsoleApplication1.obj
    • ②.搜索“test”,将内容复制出来
    • ③.打开工具路径,我的路径是:C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x86
    • ④.使用cmd命令查看:undname XXX
?test@@YAHH@Z
?test@@YAHN@Z
?test@@YAHHN@Z

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

三、函数指针

  • 什么是函数指针:每一个函数都占用一段内存单元,它们有一个起始地址,指向函数入口地址的指针称为函数指针
  • 函数指针的一般形式数据类型(*指针变量名)(参数表); —— int(*p)(int);
  • 返回指针的函数int* p(int);,这个是函数,返回的值是一个指针
  • 示例:函数指针
int MaxValue(int x, int y)
{
	return (x > y) ? x : y;
}
int MinValue(int x, int y)
{
	return (x < y) ? x : y;
}
int Add(int x, int y)
{
	return x + y;
}
bool ProcessNum(int x, int y, int(*p)(int a, int b)) // 这个也称为回调函数
{
	cout << p(x, y) << endl;
	return true;
}

int main()
{
	int x = 10, y = 20;
	cout << ProcessNum(x, y, MaxValue) << endl;
	cout << ProcessNum(x, y, MinValue) << endl;
	cout << ProcessNum(x, y, Add) << endl;

	return 0;
}

四、命名空间

  • 命名空间概念:命名空间这个概念,可作为附加信息来区分不同库中相同名称的函数、类、变量等;命名空间即定义了上下文;本质上命名空间就是定义了一个范围
  • 命名空间关键字:using和namespace
//命名空间声明
namespace quickzhao
{
	int test(int a);
}

//命名空间定义
namespace quickzhao
{
	int test(int a)
	{
		return a+1;
	}
}

//调用
int main()
{
	int result;
	result = quickzhao::test(1);
	
    return 0;
}

五、内联(inline)函数

  • 内联函数概念:如果一个函数是内联的,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方
  • 引入内联函数的目的:为了解决程序中函数调用的效率问题;注意 —— 内联函数内部不能有太复杂的逻辑,编译器有时会有自己的优化策略,所以内联不一定起作用
#include <iostream>

using namespace std;

inline int MaxValue(int a, int b)
{
	return (a > b) ? a : b;
}

int main()
{
	int x = 3, y = 4;
	MaxValue(x, y);

	return 0;
}

六、递归

1 - 递归的基本法则

  • 递归的四个基本法则
    • 基准情形:无须递归就能解出
    • 不断推进:每一次递归调用都必须使用求解状况朝接近基准情形的方向推进
    • 设计法则:假设所有的递归调用都能运行
    • 合成效益法则(compound interest rule):求解一个问题的同一实例时,切勿才不同的递归调用中做重复性的工作
  • 递归实现 —— 斐波那契数列:由递归的四个基本法则来看,使用递归来计算诸如斐波那契数列并不是一个好主意

2 - 递归的缺陷与优化

  • 递归是一种重要的编程思想
    • 很多重要的算法都包含递归的思想
    • 递归最大的缺陷
      • 空间上需要开辟大量的栈空间
      • 时间上可能需要有大量重复运算
  • 递归的三种优化方案
    • a)尾递归:所有递归形式的调用都出现在函数的末尾
    • b)使用循环替代
    • c)使用动态规划,空间换时间

3 - 递归实现—斐波那契数列

  • 递归实现—斐波那契数列
#include <iostream>
#include <cassert>

using namespace std;

// 斐波那契数列的实现
// 方法一:递归
int Fib(int n)
{
	if (n == 0)
	{
		return 0;
	}
	else if (n == 1)
	{
		return 1;
	}
	else
	{
		return Fib(n - 1) + Fib(n - 2);
	}
}

int main()
{
	assert(Fib(10) == 55);

	return 0;
}
  • 循环实现—斐波那契数列
#include <iostream>
#include <cassert>

using namespace std;

// 循环
int Fib3(int n)
{
	if (n < 2)
	{
		return n;
	}
	int n0 = 0, n1 = 1;
	int temp;
	for (int i = 2; i <= n; i++)
	{
		temp = n0;
		n0 = n1;
		n1 = temp + n1;
	}
	return n1;
}

int main()
{
	assert(Fib3(10) == 55);

	return 0;
}
  • 尾递归实现—斐波那契数列
// 尾递归
int Fib2(int n, int ret0,  int ret1)
{
	if (n == 0)
	{
		return ret0;
	}
	else if (n == 1)
	{
		return ret1;
	}
	return Fib2(n - 1, ret1, ret0 + ret1);
}
  • 动态规划实现—斐波那契数列
int g_a[1000]; // 全局的数组,记录斐波那契数列的前1000个值

// 动态规划
int Fib4(int n)
{
	//assert(n >= 0);
	g_a[0] = 0;
	g_a[1] = 1;
	for (int i = 2; i <= n; i++)
	{
		if (g_a[i] == 0)
		{
			g_a[i] = g_a[i - 1] + g_a[i - 2];
		}
	}
	return g_a[n];
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无休止符

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值