C++---函数内联

来源:互联网 发布:apache启动不了的原因 编辑:程序博客网 时间:2024/05/22 17:38

首先 ,说起内联函数,有必要将C语言中的宏介绍下。

<span style="font-size:18px;">#define  Mul(x) (x*x)</span>

上面就定义了一个宏。那么,我们为什么要使用宏呢? 因为函数的调用需要将程序的执行顺序转移到函数存放的内存中,将函数执行完后 ,再返回到之前执行该函数的地方。这种 函数调用的过程需要一定的时间和内存空间的开销,从而影响程序执行的效率。而宏只是在预处理的地方把代码展开,不需要额外的空间和时间开销,所以调用宏比调用函数更有效率。


在这里就简单 总结下宏的优缺点:

优点:1、宏的执行效率高 ; 2、宏能增强代码的复用性 

缺点:1、宏不方便调试 ; 2、宏没有类型新型安全检查 ; 3、可维护性差 , 容易误用 ; 4、宏不能访问对象的私有成员

    比如上面的代码 如果 这样调用宏函数 Mul(10+10),我们想要得到的结果是400 ,而实际测得结果为120 ,为什么呢?因为宏在替换的时候直接回把代码的原型搬过来 , 也就是   10+10*10+10    所以会产生误用 。

    当然也可以给宏的参数加上括号 :#define   Mul(x)  ( (x)*(x) )。 但是这样还是能出现问题,例如:Mul( a++)  ,变量a取值5  ,那么 我们希望的结果是25 , 实际测得30 , 这又是为什么? 同样,函数会直接把代码搬过来   (a++)*(a++), 那么函数在执行的过程中++会执行两次, 最后变成了 5 * 6  , 就得到了30 


既然宏有这么多得不好 , 那么我们怎么解决这些问题呢?

这就要 谈到本篇文章的重点了:内联函数

关键字inline

    C++ 语言支持函数内联,其目的是为了提高函数的执行效率(速度)。 
     在 C程序中,可以用宏代码提高执行效率。宏代码本身不是函数,但使用起来象函数。预处理器用复制宏代码的方式代替函数调用,省去了参数压栈、生成汇编语言的 CALL调用、返回参数、执行return等过程,从而提高了速度。使用宏代码最大的缺点是容易出错,预处理器在复制宏代码时常常产生意想不到的边际效应。例如:

<span style="font-size:18px;">#define Max(a,b) (a) > (b)? (a) : (b)</span>
在调用的时候 Max(x , y)+2   会直接替换为 (x) > (y) ? (x)+(y) +2   那么结果如何呢?(提示:+的优先级比:运算符高)


内联函数的定义:inline必须与函数定义放在一起才能使函数成为内联, 仅将inline放在函数声明前面是不起作用的
 举例:

<span style="font-size:18px;">//这样的fun函数不能成为内联函数:inline  void  fun();//inline 仅与函数声明放在一起void fun(){  //Do Something}//下面的fun函数是内联函数 void  fun();inline void fun()  //inline 与函数定义放在一起{  //Do Something}</span>
可以这么理解: inline是一种“用于实现的关键字”,而不是一种“用于声明的关键字”

   一般地,用户可以阅读函数的声明,但是看不到函数的定义。尽管在大多数教科书中内联函数的声明、定义体前面都加了inline关键字,但我认为inline不应该出现在函数的声明中。这个细节虽然不会影响函数的功能,但是体现了高质量C++/C程序设计风格的一个基本原则:声明与定义不可混为一谈,用户没有必要、也不应该知道函数是否需要内联。 

定义在类声明之中的成员函数将自动地成为内联函数

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) 

… 
}


慎用内联

内联能提高函数的执行效率,为什么不把所有的函数都定义成内联函数? 
如果所有的函数都是内联函数,还用得着“内联”这个关键字吗? 
内联是以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。如果执行函数体内代码的时间,相比于函数调用的开销较大,那么效率的收获会很少。另一方面,每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。以下情况不宜使用内联: 
(1)如果函数体内的代码比较长,使用内联将导致内存消耗代价较高。 
(2)如果函数体内出现循环,那么执行函数体内代码的时间要比函数调用的开销大。 

类的构造函数和析构函数容易让人误解成使用内联更有效。要当心构造函数和析构函数可能会隐藏一些行为,如“偷偷地”执行了基类或成员对象的构造函数和析构函数。所以不要随便地将构造函数和析构函数的定义体放在类声明中。


内联函数和宏比较

1.内联函数在运行时可调试,而宏定义不可以;
2.编译器会对内联函数的参数类型做安全检查或自动类型转换(同普通函数),而宏定义则不会; 
3.内联函数可以访问类的成员变量,宏定义则不能; 
4.在类中声明同时定义的成员函数,自动转化为内联函数。


1 0
原创粉丝点击