【c++】——形参带默认值的函数、内联函数、函数重载

一、形参带默认值的函数

说到形参带默认值的函数我们还是引用我们最常写的函数,并给出语句指令执行方式如下:

#include<iostream>
#include<string.h>
using namespace std;
int sum(int a, int b)
{
	int temp = 0;
	temp = a + b;
	return temp;
}
int main()
{
	int a = 10;
	int b = 20;
	int ret = sum(a, b);
	cout << "ret:" << ret << endl;
	return 0;
}

那么形参如何给实参传参数呢?以下是给出的几种传递方式,以及传参时应该注意的规则。

规则一:给默认值的时候,从右向左给
如下的方式是正确的

int sum(int a, int b=20)
{
	int temp = 0;
	temp = a + b;
	return temp;
}

但是以下的方式就是错误的

int sum1(int a=10, int b )
{
	int temp = 0;
	temp = a + b;
	return temp;
}

因为形参是从右向左压栈

规则二:相比于不传参数,传入参数的效率更高,因为少了move指令。
我们来看看,具体的语句指令
int ret = sum(a, b);的指令如下:

mov eax,dword ptr[ebp-8]
	push eax
	mov ecx,dword ptr[ebp-4]
	push ecx
	call sum

ret = sum(a);的指令调用如下:

push 14H
	mov ecx,dword ptr[ebp-4]
	push ecx
	call sum

ret = sum2();的指令调用如下:它的效率等同于sum2(20,50)

push 14H
	push 0AH
	call sum

规则三:定义时可以给形参默认值,声明也可以给形参默认值。

申明的时候给默认值,函数体放在主函数后面

int sum3(int a = 10, int b = 20);
int main()
{
......
}
int sum3(int a, int b = 20)
{
	int temp = 0;
	temp = a + b;
	return temp;
}

规则四:形参给默认值的时,不管是定义处给还是声明处给,形参默认值只能出现一次
如下的传递方式则是错误的,形参的默认值出现了两次

int sum3(int a = 10, int b = 20);
int sum3(int a , int b = 20);

但是如下的方式则是正确的,虽然第一个的形参赋值不是从右向左的但是第二个等式弥补了错误
int sum3(int a = 10, int b );
int sum3(int a, int b = 20);

二、inline内联函数

还是使用文章最开始的时候我们给出的代码进行分析。
首先我们来探讨一下
1)什么是inline内联函数?
例如下面一段语句

int ret = sum(a+b);

此处有有函数调用的开销。包括参数压栈,函数栈帧的开辟和回退过程。
x+y 有两个指令 mov add mov 如果有10000次的x+y操作,那么将会有大量的时间用在了函数调用的开销上。

此时我们就可以使用内联函数。内联函数就是在编译过程中,就没有函数的调用开销,在函数的调用点直接把函数的代码进行展开处理(在符号表中也不用生成函数符号了)

(2)内联函数的处理过程:
就相当于在执行到int ret = sum(a, b);时,直接把sum函数展开,把a,b直接替换成了x,y变成了int ret = a+b;

(3)内联函数的注意点

  • 但是不是所有的lnline都会被编译器处理成内联函数,比如说递归

递归的结束是在运行的时候看递归条件来决定什么时候结束,但是inline是编译器处理的,他是不执行指令的

  • inline只是建议编译器把这个函数处理成内联函数
    真正是否是内联函数还是编译器决定的
  • debug版本inline函数不起作用,因为其需要调试,所以只在release版本才能出现
  • 如果这个函数在短时间内会有大量调用且简单尽量设置成内联函数

三、函数重载

说到函数重载,我们首先给出下列代码

#include<iostream>
#include<typeinfo>
using namespace std;

bool compare(int a, int b)
{
	cout << "compare_int_int" << endl;
	return a > b;

}
bool compare(double a, double b)
{
	cout << "compare_double_double" << endl;
	return a > b;

}
bool compare(const char* a, const char* b)//compare_char*_char*
{
	cout << "compare_char*_char*" << endl;
	return strcmp(a ,b)>0;

}

int main()
{
	compare(10, 20);
	compare(10.0, 20.0);
	compare("aaa","bbb");
	return 0;
}

代码执行结果为:
在这里插入图片描述
细细观察上面几个函数,我们可以发现,他们的函数名相同,只是参数列表类型不同而已,由此引出我们函数重载的定义。

(1)什么是函数重载?

  • 一组函数,函数名相同,参数列表的个数或者类型不同,那么这一组函数我们称之为函数重载
  • 一组函数要称得上重载,一定是先处在同一个作用域当中
    为了解释相同作用域是什么意思,我们举一个反例,在上面代码的基础上,我们把main函数改成这样:
int main()
{
	bool compare(int a, int b);
	compare(10, 20);
	compare(10.0, 20.0);
	compare("aaa","bbb");
	return 0;
}

编译的时候我们会发现,这个程序是错误的。

因为当有这个函数声明的时候,大家都去一股脑的调用参数类型为int的函数了,因为他们在本地的局部作用域已经看到了这个声明。出现了类型不匹配的问题。

  • 一组函数,函数名相同,参数列表也相同,仅仅是返回值不同。不叫重载
    因为,在生成符号的时候与返回值是没有关系的

(2)c++为什么支持函数重载,但是c语言不支持
c++代码产生函数符号的时候,是函数名+参数列表类型
c代码产生函数符号的时候,函数名来决定(函数名相同就会产生链接错误

发布了62 篇原创文章 · 获赞 7 · 访问量 2550

猜你喜欢

转载自blog.csdn.net/qq_43412060/article/details/104995836
今日推荐