C++中的函数玩法

编程入门 行业动态 更新时间:2024-10-24 20:13:22

C++中的函数<a href=https://www.elefans.com/category/jswz/34/1764778.html style=玩法"/>

C++中的函数玩法

内联函数(inline)

        函数调用是有时间和空间开销的。程序在执行一个函数之前需要做一些准备工作,要将实参、局部变量、返回地址以及若干寄存器都压入栈中,然后才能执行函数体中的代码;函数体中的代码执行完毕后还要清理现场,将之前压入栈中的数据都出栈,才能接着执行函数调用位置以后的代码。         如果函数体代码比较多,需要较长的执行时间,那么函数调用机制占用的时间可以忽略; 如果函数只有一两条语句,那么大部分的时间都会花费在函数调用机制上,这种时间开销就就不容忽视。         为了消除函数调用的时空开销,C++ 提供一种提高效率的方法,即在编译时将函数调用处用函数体替换,类似于 C 语言中的宏展开。 这种在函数调用处直接嵌入函数体的函数称为内联 函数( Inline Function ),又称内嵌函数或者内置函数。指定内联函数的方法很简单,只需要在函数定义处增加 inline 关键字。请看下面的例子:
#include <iostream>
using namespace std;
//内联函数,交换两个数的值
inline void swap(int *a, int *b)
{int temp;temp = *a;*a = *b;*b = temp;
}
int main()
{int m, n;cin>>m>>n;cout<<m<<", "<<n<<endl;swap(&m, &n);cout<<m<<", "<<n<<endl;return 0;
}
        当编译器遇到函数调用 swap(&m, &n) 时,会用 swap() 函数的代码替换 swap(&m, &n) ,同时用实参代替形参,以下为替换后的结果:
int main()
{int m, n;cin>>m>>n;cout<<m<<", "<<n<<endl;{int temp;temp = *(&m);*(&m) = *(&n);*(&n) = temp;}cout<<m<<", "<<n<<endl;return 0;
}
        编译器可能会将 *(&m) 、 *(&n) 分别优化为 m 、 n 。         当函数比较复杂时,函数调用的时空开销可以忽略,大部分的 CPU 时间都会花费在执行函数体代码上,所以我们一般是将非常短小的函数声明为内联函数。由于内联函数比较短小,我们通常的做法是省略函数原型,将整个函数定义(包括函数头和函数体)放在本应该提供函数原型的地方,也就是声明时定义。         注意:要在函数定义处添加 inline 关键字,在函数声明处添加 inline 关键字虽然没有 错,但这种做法是无效的,编译器会忽略函数声明处的 inline 关键字。         使用内联函数的缺点也是非常明显的,编译后的程序会存在多份相同的函数拷贝,如果被声明为内联函数的函数体非常大,那么编译后的程序体积也将会变得很大,所以再次强调,一 般只将那些短小的、频繁调用的函数声明为内联函数。

         对函数作 inline 声明只是程序员对编译器提出的一个建议,而不是强制性的,并非一经指定为 inline 编译器就必须这样做。编译器有自己的判断能力,它会根据具体情况决定是否这样做。

内联函数和宏定义的区别

        使用宏代码最大的缺点是容易出错,预处理在拷贝宏代码时常常产生意向不到的边际效应。 例如:
#define MAX(a,b) (a)>(b)?(a):(b)
//语句为
result = MAX(i,j)+2;
//被预处理器扩展为
result = (i)>(j)?(i):(j)+2;

由于运算符"+"比运算符"?:"的优先级高,所以上述语句并不等价于

result = ((i)>(j)?(i):(j))+2;

如果把宏代码改写为:

#define MAX( a , b ) ((a) > (b) ? (a) : (b))
则能解决优先级的问题。但是会引发另一个问题
result = MAX (i++,j); // 被预处理器扩展为 result = (i++)>(j)?(i++):(j) // 在同一个表达式中 i 被两次求值。
        宏的另一个缺点是不可调试。内联机制既具备宏代码的效率,又增加了安全性,而且可以自由操作的类的数据成员,所以应该尽量使用内联函数来取代宏代码。

默认参数

在 C++中,可以为函数的形参指定默认的参数值,例如:

int sun(int a,int b = 3,int c = 7);
int Opendev(int cfg,char *name = "1.txt");
        如上,这样我们在调用函数的时候,就可以只选择传递没有默认参数的形参,例如,在调用上面 sun 的时候,我就可以
sun(3);
//或
sun(3,4);
//或
sun(3,4,5);

注意事项

在声明默认参数时,必须是从右向左声明,也就是说,没有默认参数的形参应该全部在前面,下面这些就是错误示例:
int fun ( int a , int b = 1 , int c ); void run ( char* name = "2.bmp" , int cfg );

占位参数

        在 c++中提供了占位参数用于程序扩展和对 C 语言的兼容,什么是占位参数呢,就是只声明数据类型而没有形参名称,一般在函数体内部无法使用该参数,例如:
int func(int a, int b, int)
{return a+b;
}
int main(int argc, char *argv[])
{printf("fun(1,2,3) = %d\n", func(1,2,3));printf("Press enter to contiue ...");return 0;
}
一般占位参数配合默认参数一起使用,例如:
int func(int a, int b, int = 0)
{return a+b;
}
int main(int argc, char *argv[])
{printf("func(1,2) = %d\n", func(1,2));printf("Press enter to continue ...");return 0;
}
这样在调用的时候,你就可以把上面的 func 函数当作一个两参数函数使用。

函数重载

        c++的三大特性,封装,继承,多态,其中多态又分为编译时多态和运行时多态,本次要谈的函数重载便是 C++编译时多态的一种体现。         前面章节我们讲过,在 C++中,函数会被经过换名处理,新的名字是受返回值,函数名,形参决定,所以只要是参数类型不同,参数个数不同,参数的顺序就可以定义相同的函数名。 例如:
#include <iostream>
using namespace std;
int sun(int a,int b);
int sun(int a,int b,int c);
int main()
{cout<<sun(1,2)<<endl;return 0;
}
int sun(int a,int b)
{return a+b;
}
int sun(int a,int b,int c)
{return a+b+c;
}
在编译的时候,系统会根据你传递的实参个数或类型来匹配对应的函数,这就叫函数重载。

注意事项

C++函数重载必须要满足的条件是: 1.函数名相同。 2.参数列表相同。 当函数重载遇上默认参数的时候,情况例如下面所示:
int sun ( int a , int b ); int sun ( int a , int b , int c = 3 );
        因为带默认参数的函数,传递参数时传递的个数是可变的,那么当遇上上面情况时,如果调用 sun(2,3)就会报错,会产生模糊的调用,而调用 sun(2,3,4)则可以正确的重载到 sun(int a,int b,int c =3)这个函数。

更多推荐

C++中的函数玩法

本文发布于:2023-11-16 10:07:20,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1617540.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:玩法   函数

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!