一、c++ inline函数产生原因

由于函数调用会有一定的时间和空间方面的开销,特别是对于一些函数体代码不大但又被频繁调用的函数来讲,效率是很低的。

在C语言中,可以用宏函数来提高上面那种情况的效率,但宏函数有些缺点,它只是提供一个文本替换的功能,而不是一个真正的函数。所以在C++中引入了inline函数来解决这个问题,它会像宏函数一样在调用函数处用内联函数体的代码进行替换,还遵循函数的类型和作用域规则,所以它能像一般的函数那样进行调用和调试。

二、如何定义inline函数

inline函数只有和函数体定义放在一起是才有效,所以如果像这样声明一个内联函数

  1. inline void Func(); 

那么在编译器看来,它与普通函数没有两样,如下所示

  1. inline void Func()  
  2. {  
  3. // ...  

这样它才具有比一般函数更快的执行能力。

还有一种定义方式是在类内部定义的函数。在c++中,如果在类内部定义了函数体的函数,则默认其为内联,而不管是否有inline关键字。所以像如下两个函数Func1、Func2都属于内联。

  1. class A  
  2. {  
  3. public:  
  4.     inline void Fun1(){ //... }  
  5.     void Fun2(){ //... }  

当然,内联函数并不是万能的,在某些情况下,它不仅不能像期望的那样提升性能,甚至会起反作用。inline只是对编译器的一种提示,而不是命令。也就是说,只要编译器愿意,它就可以随意地忽略掉你的指令,当编译器遇到内联函数时,就会针对函数体的上下文进行优化,以确定是否执行内联。如果编译器认为当前的函数过于复杂、函数体过大,或者这个函数是虚函数,就会拒绝将其内联,这取决与编译器,不同编译器处理方式不一样。

三、在使用inline时,需注意如下几点:

1、在inline函数内不允许用循环语句和开关语句,函数体不能过于复杂;

2、对于内存空间有限的机器而言,慎用内联。过分使用内联会造成函数代码过于膨胀,会占用太多空间;

3、不能对构造或者析构函数进行内联,尽管它们看似很简短。对于这一点看下面这个类Derived的构造函数:

  1. class Base  
  2. {  
  3. public:  
  4.     ...  
  5. private:  
  6.     string s1, s2;  
  7. };  
  8.  
  9. class Derived: public Base  
  10. {  
  11. public:  
  12.     Derived(){}  
  13.     ...  
  14. private s3, s4, s5;  
  15. }; 

这个构造函数看起来的确是个内联的好材料,因为它没有代码,实际上,它含有相当多的代码。对于上面这个空的Derived的构造函数,有些编译器会为它产生相当于下面的代码:

  1. // 一个Derived构造函数的可能的实现  
  2. Derived::Derived()  
  3. {  
  4.     // 如果在堆上创建对象,为其分配堆内存  
  5.     if (本对象在堆上)  
  6.     {  
  7.         this = ::operator new(sizeof(Derived));  
  8.     }  
  9.     // 初始化父类对象  
  10.     Base::Base();  
  11.     s3.string();    // 构造s3  
  12.     s4.string();    // 构造s4  
  13.     s5.string();    // 构造s5  

如果string的构造函数也恰巧被内联,Derived的构造函数将得到其代码的5个拷贝(2个继承而来,3个自己声明)。现在你应该明白,内联Derived的构造函数并非可以很简单就决定的;类似的情况也适用于析构。

4、内联函数只适合于只有1~5行的小函数。

四、内联还得面临2个头疼的问题

第一,该如何维护?一个函数开始的时候可能满足了设定的内联标准,并以内联的形式出现,但随着系统的扩展升级,函数体中增添了一些新功能,函数体变得复杂了,这就使内联函数不再适合内联,此时需要把函数前面的inline去掉,并把函数体放到相应的源文件中,这会使维护的难度有所增加。

第二,不可避免的重新编译。当内联函数实现改变的时候,用户必须重新编译他们的代码以反映出这种改变。而对于非内联函数,我们仅仅需要重新链接。

所以,使用inline需要依靠积累的经验来进行判断,合理正确的使用内联,可以提高程序的性能,反之,会带来意想不到的副作用!