C++ inline函数

1.C++引用inline原因

在我们的系统中可能经常会有一些场景:for循环调用一个工具处理函数或则是递归调用一些算法。我们知道调用一个任意函数都会为这个函数创建栈空间,如果频繁的调用小函数会消耗大量的栈空间,对内存造成很大的压力,甚至会导致内存枯竭。C++为了解决这个问题也就创造了内联函数,也就是inline。

下面我们看一个使用内联函数的例子:

#include 
//函数定义为inline即:内联函数
inline char* dbtest(int a) {
    return (i % 2 > 0) ? "奇" : "偶";
} 

int main()
{
   int i = 0;
   for (i=1; i < 100; i++) {
       printf("i:%d    奇偶性:%s /n", i, dbtest(i));    
   }
}

上面的函数通过一个循环,然后循环的调用dbtest()函数,如果dbtest函数不声明为inline,系统会调用一百次dbtest函数,创建100次栈空间。

但是这里我们将dbtest函数声明成inline函数之后,任何调用dbtest(i)的地方都换成了(i%2>0)?”奇”:”偶”,这样就避免了频繁调用函数对栈内存重复开辟所带来的消耗。

2.inline函数使用限制与建议

inline函数虽然对内存有极大的优化,但是也不是随处可用的,我们发现inline函数有点类似于编译器把调用函数的地方改为一份函数代码的副本调用替代,而不用调用一次函数。

所以,inline只适合涵数体内代码简单的涵数使用,不能包含复杂的结构控制语句例如while、switch,并且不能内联函数本身不能是直接递归函数(即,自己内部还调用自己的函数)。

inline函数也不是一定会生效,这个修饰只是对编译器的一个建议,所以最后能否真正内联,看编译器的意思,它如果认为函数不复杂,能在调用点展开,就会真正内联,并不是说声明了内联就会内联,声明内联只是一个建议而已。

其次,因为内联函数要在调用点展开,所以编译器必须随处可见内联函数的定义,要不然就成了非内联函数的调用了。所以,这要求每个调用了内联函数的文件都出现了该内联函数的定义。

声明跟定义要一致:如果在每个文件里都实现一次该内联函数的话,那么,最好保证每个定义都是一样的,否则,将会引起未定义的行为。如果不是每个文件里的定义都一样,那么,编译器展开的是哪一个,那要看具体的编译器而定。所以,最好将内联函数定义放在头文件中。

3. inline使用注意点

类中成员函数与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 必须与函数定义体放在一起才能使函数成为内联,仅将inline 放在函数声明前面不起任何作用。

如下风格的函数Foo 不能成为内联函数:

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 是一种“用于实现的关键字”,而不是一种“用于声明的关键字”。

慎用inline

不是所有的函数都要用inline,内联是以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。 如果执行函数体内代码的时间,相比于函数调用的开销较大,那么效率的收获会很少。另一方面,每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。

你可能感兴趣的:(C++)