目录
- C++语言支持函数内联,其目的是为了提高函数的执行效率(速度)
在C程序中,可以用宏代码提高执行效率。宏本身不是函数,但使用起来像函数。预处理器用复制宏代码的方式替换函数调用,省去了参数压栈、生成汇编语言的CALL调用、返回参数、执行return等过程,从而提高了速度。使用宏代码最大的缺点是容易出错,预处理器在复制代码时常常产生意想不到的边际效用,如:
- #define MAX(a,b) (a)>(b)?(a):(b)
-
- int fun()
- {
- result=MAX(i,j)+2;
- }
预处理器在处理result时, result=(i)>(j)?(i):(j)+2; 由于运算符' + '的优先级比‘ j ’优先级高,所以该语句的执行为:result=((i)>(j)?(i):(j))+2; 这并不是我们期待的结果。对宏定义添加括号,改为如下所示的代码可以处理该问题
#define MAX(a,b) ((a)>(b)?(a):(b))
这是一个问题,对于C++而言,使用宏定义还有一个缺点就是:无法操作类的私有数据成员。
因此引入“内联函数”,在C++程序中,应该用内联函数取代所有宏代码,而且内联函数可以对类型安全检查或者自动类型转换。
- 内联函数是函数,宏是预处理命令
- 内联是运行时执行,宏是编译之前执行
- 内敛不会出现歧义,宏会出现歧义
- 二义性:
- 例如 #define S(a,b) a+b
- 在main函数内计算 S(3,4)/S(3,4)=3+4/3+4,而不是1
- 写的时候写到不能加括号为止,用的时候原模原样替换
关键字inline必须与函数定义体放在一起才能使函数称为内联,仅将Inline放在函数声明前面不起任何作用。如下所示:
- //错误:
- inline void Foo(int x,int y);//inline仅仅和函数声明放在一起
- void Foo(int x,int y)
- {
- ...
- }
-
- //正确:
- void Foo(int x,int y);
- inline void Foo(int x,int y)//inline与函数定义体放在一起
- {
- ...
- }
所以说,inline时一种“用于实现的关键字”,而不是一种“用于声名的关键字”。
定义在类声明的成员函数将自动地成为内联函数。例如:
- class A
- {
- public:
- void Foo(int x,int y){...}//自动成为内联函数
- };
但是将成员函数的定义体放在类声明中虽然能带来书写上的方便,但不是一种良好的编程风格,上例应该写为:
- //头文件
- class A
- {
- public:
- void Foo(int x,int y);
- };
- //定义文件
- inline void A::Foo(int x,int y)
- {
- ...
- }
- 函数调用会有空间上和时间上的消耗
- 有一些函数只做简单功能(赋值、返回、输出...),就可以直接把函数的函数体放在类内
- 把代码比较短小,功能比较简单的一些函数,放在类里面直接定义,函数调用时直接将函数体嵌入到当前调用处,直接执行,不会有函数调用的转移。
- 显示内联
- 隐式内联
- 类内定义的内联函数叫做隐式内联 //功能简短编译器会当作内联函数,有些即便在函数名处写了inline但编译器发现函数体比较复杂时,也不会当作内联函数进行编译。函数体名前加入inline是程序员对其的建议。
- 例如在执行简单的printf函数时,实现是将代码嵌入到主函数内,而复杂函数是执行跑到函数内部,增加了函数时间上的消耗,但是节省了空间的消耗,内嵌函数则相反。
- 显示内联:函数名前写inline且函数体比较短小,编辑器会按照inline进行编译。
内联函数提高执行效率是以代码膨胀(复制)为代价的。主函数在调用时候,是将内联函数的代码直接放在了主函数的位置上,所以没有指令跳转。指令按顺序执行如果执行函数体内代码的时间,相比于函数调用的开销大,那么效率收获会很少。
- 函数体内代码比较长,使用内联函数将导致内存消耗代价较高
- 函数体内出现循环,那么执行函数体内代码的时间要比函数调用的开销大