宏与内联函数

来源:互联网 发布:网络词汇 编辑:程序博客网 时间:2024/06/05 04:24

             函数作为一种抽象机制,对解决大型复杂问题起到了很大作用。但是,由于函数调用时需要开销的,例如,函数调用时需要保护调用者的运行环境,进行参数传递,执行调用命令,为局部变量分配空间以及执行返回指令等,因此函数会带来程序执行效率的下降,特别是对一些小函数的频繁调用。

         c++提供了两种解决上述问题的办法:宏定义和内联函数。

         1.宏定义

          宏定义是c++的一种编译预处理命令,它用#define来实现。在c++中,宏定义有4中格式:

         (1)#define  宏名  文字串

                  如:#define  PI  3.1415

                  在编译前,把程序文本中出现“宏名”的地方用“文字串”进行替换,它主要用于符号常量的定义。

          

         (2)#define  宏名(参数表)   文字串

                 如:#define max(a,b)  a>b?a:b

                        int main()

                       {

                                    int x ,y;

                                    .......max(x,y)....;       //编译前,替换成.......x>y?x:y.......

                                    .....................

                       }

                 替换后进行编译,避免了函数调用所需开销。这种宏定义主要解决对小函数频繁调用效率不高的问题。宏定义是纯粹的文本替换,如要运算10+max(x,y)+z ;替换后是10+x>y?x:y+z ;根据运算符的优先级,它的含义是(10+x)>y?x:(y+z) ; 显然不是我们所要的;因此我们应尽量给宏定义中所有参数带上括号,如:#define max(a,b)  (((a)>(b))?(a):(b)) 

 

            (3) #define 宏名

            该宏定义只是告诉编译程序该“宏名”已被定义,它并不做任何程序文本替换,其作用是实现条件编译。

       

            (4) #undef 宏名

             取消某个宏名的定义,其后的“宏名”不在进行程序文本替换和不在有定义。

            

             2.内联函数

             宏定义是c++从c中保留下来的,虽然它可以解决函数调用效率不高的问题,但它也存在一些不足:

              (1) 有时会出现重复计算,例如对于上面的宏定义:max(i++ , j++)  编译预处理系统会把它替换成

              (((i++)>(j++))?(i++):(j++)) 不管i++还是j++大,i++或j++都会被计算两次

 

              (2) 不进行参数类型检查和转换,只进行简单文字替换。

 

              (3)  不利于一些工具对程序的处理。在c++的编译结果中,所有的宏定义都已经不存在了,这就会给一些软件工具(如调试程序)在源程序与目标程序之间进行交叉定位带来困难。

 

              鉴于以上因素,c++提供了另外一种解决函数调用效率不高的机制:内联函数。即在函数的定义中,可以在函数返回类型前加上关键字inline,其作用是建议编译程序把该函数的函数体展开到调用点,内联函数形式上属于函数而又有宏定义的高效率。

             如:

               inline  int  max(int a , int b)

               {

                      return a>b?a:b ;

                }         

              使用内联函数时注意:

              (1) 编译程序对内联函数的限制。给函数定义加上inline 只是建议编译程序把该函数当内联函数来处理,至于编译程序是否把它当内联函数处理,这要视具体情况而定。有些函数定义即使加上关键字inline,编译程序也不会把它当内联函数处理,例如递归函数(或函数体内的代码太多)。

              (2) 内联函数名具有文件作用域,即各个源文件中定义的同名内联函数属于不同的函数。在使用同一个内联函数的各个源文件中都要对其定义,所以一般把内联函数的定义放在某个头文件中,使用该内联函数的源文件需要把该头文件包含进来。

              (3)默认情况下,编译程序会把c++类中的成员函数当内联函数来处理,而在类外部定义的成员函数需要显示的加上关键字inline , 编译程序才会把它当内联函数处理。

          

           以上大部分出自《程序设计教程》(用c++语言编程)

         

原创粉丝点击