一、内联函数概念
在c 中,预定义宏的概念是用内联函数来实现的,而内联函数本身也是一个真正的函数。 内联函数具有普通函数的所有行为。唯一不同之处在于内联函数会在适当的地方像预定义宏 一样展开,所以不需要函数调用的开销。因此应该不使用宏,使用内联函数。 在普通函数(非成员函数)函数前面加上inline关键字使之成为内联函数。但是必须注意必须 函数体和声明结合在一起,否则编译器将它作为普通函数来对待。
这个写法没有任何效果,仅仅是声明函数
代码语言:javascript复制inline void func(int a);
应该用下面的写法
代码语言:javascript复制inline int func(int a){
return ;
}
注意: 编译器将会检查函数参数列表使用是否正确,并返回值(进行必要的转换)。这些事预 处理器无法完成的。
内联函数的确占用空间,但是内联函数相对于普通函数的优势只是省去了函数调用时候的压 栈,跳转,返回的开销。我们可以理解为内联函数是以空间换时间。
二、宏函数和内联函数区别
宏函数的替换是发生在预处理阶段 内联函数的替换是发生在编译阶段
宏函数容易出错,但是内联函数不会
我们希望的是 c = (10 20 )* 5,但是用宏函数出现的却会为a b * 5
代码语言:javascript复制#define MYADD(a,b) a b
int main()
{
int a = 10;
int b = 20;
int c = MYADD(a, b)*5;
}
当然我们也可以用内联函数既能和宏函数一样,都省去了调用函数的开销,也能实现(a b )* 5的操作,相当于没有调用函数。
代码语言:javascript复制inline int myadd(int a, int b)
{
return a b;
}
int main()
{
int a = 10;
int b = 20;
int c = myadd(a,b) *5;
}
任何在类内部定义的函数自动成为内联函数。
代码语言:javascript复制class Person{
public:
Person()
{
cout << "构造函数!" << endl; }
void PrintPerson(){ cout << "输出Person!" << endl;
}
}
三、内联函数和编辑器
对于任何类型的函数,编译器会将函数类型(包括函数名字,参数类型,返回值类型)放入到 符号表中。
同样,当编译器看到内联函数,并且对内联函数体进行分析没有发现错误时,也 会将内联函数放入符号表。
当调用一个内联函数的时候,编译器首先确保传入参数类型是正确匹配的,或者如果类型不 正完全匹配,但是可以将其转换为正确类型,并且返回值在目标表达式里匹配正确类型,或 者可以转换为目标类型,内联函数就会直接替换函数调用,这就消除了函数调用的开销。假 如内联函数是成员函数,对象this指针也会被放入合适位置。
类型检查和类型转换、包括在合适位置放入对象this指针这些都是预处理器不能完成的。 但是c 内联编译会有一些限制,以下情况编译器可能考虑不会将函数进行内联编译:
不能存在任何形式的循环语句 不能存在过多的条件判断语句 函数体不能过于庞大 不能对函数进行取址操作 内联仅仅只是给编译器一个建议,编译器不一定会接受这种建议