内联函数:
使用原因:为了解决频繁调用大小函数大量消耗栈(栈内存)空间的问题,引入了inline修饰符。
如:
inline int Max(int a ,int b)
{
return a+b;
}
内联函数的处理方式就是直接在函数的调用点,直接将代码展开,就相当于直接把这个函数的函数体,直接复制了一份放在了当前调用点的位置,这样做的目的就是减少了函数调用中的开栈和清栈。
如下:
左边为普通的函数调用 ,右边为引用函数的调用
普通函数调用点,实参压入栈中,然后处理函数体。
内联函数调用点,函数没有开辟栈帧和清栈,函数直接在调用点展开。(主要开销是)现场保护和现场恢复
内联函数内部尽可能只有 的单一语句(不能包含条件语句和循环语句)
内联函数和普通函数的区别:
- 内联函数在调用点代码直接展开,没有开栈和清栈的开销。普通函数有。
- 如果内联函数的函数体过于复杂,会被当做普通函数处理。
内联函数和static函数的区别: - static修饰的函数处理机制,只是将函数的符号变为局部符号,函数的处理机制和 普通函数相同。也有开栈和清栈。
- inline函数是在代码调用点直接展开导致函数本文件可见,static函数本文件可见是因为static的修饰,是全局符号变为局部符号。
内联函数和宏的区别: - inline函数的处理机制是在编译阶段,有安全检查和类型检查
宏是在预编译阶段,简单的文本替换。 - inline函数是更安全的宏。不生成符号
不是所有情况都是用inline函数,因为是典型的空间换时间,但是如果inline函数过多,导致所在文件过于庞大,就会被当做普通函数处理。
inline函数使用的限制:
- inline函数一般写在头文件中。
“.h”
- inline函数只在realse版本下生效,debug没用。
- inline函数只是给编译器的一个建议。使用决定权归编译器所有。
函数默认值:
void fun(int a = 0,int b = 0,int c = 20)
{
printf("a = %d,b = %d,c= %d\n",a,b,c,d);
}
输出 a = 0 b = 0 c = 20
- 在函数申明或者定义的时候,给定参数默认值,如果实参传递时,不能给该形参传值,则会按照前默认值传值
- 函数参数的默认值时在编译期生成指令时,直接生成入参指令
- 函数参数默认值只能传递常量
- 函数的默认值只能从右往左依次赋值
int main()
{
fun(12); //12<--0<--0
fun(12, 13);//12<--13<--0
fun(12, 13, 14); //12<--13<--14
fun(12, , 14);//赋值是从右往左,依次赋值
}
- 函数中的默认值参数在作用域,只能赋值一次,不能多次赋值
- 因为函数参数的默认值是在编译期带入的,所以函数参数的默认值只在本文件中生效。
函数重载:
函数的原型包括函数返回类型,函数名,形参列表(其中形参名省略),且不需要函数体。
:
重载函数通常用来在同一个作用域内 用同一个函数名 命名一组功能相似的函数,这样做减少了函数名的数量,避免了名字空间的污染,对于程序的可读性有很大的好处
- 函数名称必须相同。
- 参数列表必须不同(个数不同、类型不同、参数排列顺序不同等)。
- 函数的返回类型可以相同也可以不相同。
- 仅仅返回类型不同不足以成为函数的重载。,在调用时会造成二义性
int Max(int a, int b);
char Max(char a, char b);
int Max(char,char b,char c);
double Max(double a, double b);
int main()
{
int x = Max(12,23);
char ch = Max('a','b');
double dx = Max(12.23,34.45);
}
void fun(int a){}
void fun(const int b){}
//再按照 值传递,在识别函数声明相同时,并不考虑const和volatile修饰符
//调用的时候,不知道调用哪一个
//按照指针传递,
void fun(int *a){},void fun(int &a){}
void fun(const int *b){} ,void fun(int &a){}
int main() //可以
{
int a = 10;
const int b = 20;
fun(&a); fun(a); //可以
fun(&b); fun(10);
}
//不可以重载
void fun(int a){}
void fun(int a, int b =20); //不可以 ,有二义性
//可以重载
void fun(int *p)
void fun(const int* p)
//不可以重载:
void fun(int *p)
void fun(int *const p)
**函数重载属于一种静态多态
-
为什么C语言不能支持函数重载?
在编译.c文件时,会将函数的参数列表去掉,只是给函数进行简单的重命名
如:void add(int a,int b) ----> _add
所以如果参数类型,参数个数,等构成重载的条件,都没用。调用者在调用的时候看到的只有相同的函数名
而.cpp文件采用了如下图的方式来对函数进行编译:因为进行了名字粉碎技术
在编译之后 函数名就不同了
‘?’
表示名称开始
‘Add’
是函数名
“@@YA”
表示参数表的开始
“MMM”
“HHH”
表示返回值的类型,两个参数的类型
“@Z”
表示名称结束。 -
C++是否可以按照C风格编写 函数名前加extern “c” 即可
#include<iostream>
#include<windows.h>
extern "C" int Add(int a,int b)
{
return a+ b;
}
int main()
{
cout<<Add(2,6)<<endl;
system("pause");
return 0;
}