内联函数
1、内联函数的引出
背景----预处理宏会出现2个问题
1)宏看起来像一个函数调用,但是会有隐藏一些难以发现的错误;
2)预处理器不允许访问类的成员,也就是说预处理器宏不能用作类的成员函数。
为了保持预处理器宏函数的效率,没有函数调用时开销,然后又可以像普通函数那样,可进行参数、返回值得安全检查,又可以作为成员函数。
2、内联函数
2.1基本概念
内联函数本身就是真正的函数。内联函数具有普通函数的所有行为,唯一不同之处在于内联函数会在适当的地方像预定义宏那样展开,所以不需要函数调用的开销。
在普通函数(非成员函数)函数前面加上inline关键字使之成为内联函数。但是必须函数体和声明结合在一起,否则编译器将它当做普通函数来对待。
注:编译器将会检查函数参数列表使用是否正确,并返回值(必要的转换)。这些事预处理器无法完成。
内联函数的确占用空间,但是内联函数相对于普通函数的优势只是省去了函数调用时候的压栈、跳转、返回的开销。我们可以理解为内联函数是以空间换取时间。
2.2 类内的内联函数
任何在类内部定义的函数自动成为内联函数。
2.3 内联函数和编译器
对于任何类型的函数,编译器会将函数类型(包括函数名、参数类型、返回值类型)放入到符号表中,内联函数也不例外。当调用一个内联函数时,编译器首先确保传入参数类型是正确匹配的,或者如果类型完全不匹配,但是可以将其转换为目标类型,内联函数就会直接替换函数调用,这就消除了函数调用的开销。假如内联函数是成员函数,对象this指针也会被放到合适位置。
C++会有一些限制,以下情况可能才会考虑将函数进行内联编译:
- 不能存在任何形式的循环语句;
- 不能存在过多的条件判断语句;
- 函数体不能过于庞大;
- 不能对函数进行取址操作
注意:
内联函数只是给编译器的一个建议,编译器不一定会接受这种建议,如果没有将函数声明为内联函数,那么编译器也可能将此函数作内联编译。一个好的编译器将会内联小的、简单的函数。
1)函数的默认参数从左至右,如果一个参数设置了默认参数,那么这个参数之后的参数就必须设置默认参数;
2)如果函数声明和函数定义分开写,函数声明和函数定义不能同时设置默认参数。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
//定义一个加法
#define MyAdd(x,y) ((x)+(y)) //同(x+y)
void test01()
{
int ret = MyAdd(10, 20)*2;
cout << "ret=" << ret << endl;
}
#define MyCompare(a,b) ((a)<(b))?(a):(b)
//宏函数没有定义域
//内联函数
inline void mycompare(int a, int b)
{
int ret = a < b ? a : b;
cout << "ret:::" << ret << endl;
}
//内联函数的注意事项
//类内部的成员函数默认前面会加inline关键字
inline void func(); //内联函数声明
void func(); //如果函数实现时候,没有加inline关键字,依然当做普通函数对待
void test02()
{
int a = 10;
int b = 20;
//int ret = MyCompare(++a, b); //((++a)<(b))?(++a):(b) 预期结果11 出现宏缺陷
//cout << "ret=" << ret << endl;
mycompare(++a, b);
}
int main(void)
{
test02();
system("pause");
return 0;
}
3、默认参数设置
C++在声明函数时,可以设置占位参数,占位参数只有参数类型声明,而没有参数名声明。一般情况下,在函数体内部无法使用占位符。
void fun(int)占位参数,调用是必须要提供这个参数,占位参数也可以设置默认值。
C语言中没有默认参数和占位参数。
#include<iostream>
using namespace std;
void fun(int a=10, int b=10)
{
cout << "a+b=" << a + b << endl;
}
//函数 占位参数
//如果有了占位参数,函数调用时候必须要提供这个参数,但是用不到参数
//占位参数没有什么大用途,只有后面重载++符号才有一点点用
//参数可以有默认值,那么函数实现时候必须没有
//函数声明和实现里,只能有一个里有默认参数,不要同时都出现默认参数
void myfun(int a = 10, int b = 20);
void myfun(int a, int b);
void fun2(int a, int)
{
}
void test01()
{
fun(10);
fun(10, 100);
fun();
}
int main(void)
{
test01();
system("pause");
return 0;
}