欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C++inline函数

程序员文章站 2024-03-23 15:07:40
...

一、函数简介

在C/C++中,为了解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题,特别引入了inline修饰符,表示为内联函数。

栈空间就是指放置程序的局部数据(也就是函数内数据)的内存空间。

 inline 定义的类的内联函数,函数的代码被放入符号表中,在使用时直接进行替换,(像宏一样展开),没有了调用的开销,效率也很高。

内联函数具有一般函数的特性,它与一般函数所不同之处在于函数调用的处理。

  • 如何定义inline函数

    在函数声明或定义中函数返回类型前加上关键字inline,即可以把函数指定为内联函数。关键字inline必须与函数定义放在一起才能使函数成为内联,仅仅将inline放在函数声明前面不起任何作用。inline是一种“用于实现的关键字”,而不是一种“用于声明的关键字”。

 

二、编译器对inline函数的处理方法

inline对于编译器而言,在编译阶段完成对inline函数的处理。将调用动作替换为函数的本体。
(1)将inline函数体复制到inline函数调用点处;
(2)为所用inline函数中的局部变量分配内存空间;
(3)将inline函数的的输入参数和返回值映射到调用方法的局部变量空间中;
(4)如果inline函数有多个返回点,将其转变为inline函数代码块末尾的分支(使用GOTO)。

 

三、inline使用限制

inline的使用是有所限制的,inline只适合函数体内代码比较简单的函数,不能包含复杂的结构控制语句如while、switch,并且函数本身存在递归也不能内联。

 

四、inline只是对编译器的一个建议

inline函数仅仅是一个对编译器的建议,所以最后能否真正内联,看编译器的意思,它如果认为函数不复杂,能在调用点展开,就会真正内联,并不是说声明了内联就会内联,声明内联只是一个建议而已。如果函数太复杂,代码膨胀带来的恶果很可能会大于效率的提高带来的益处。内联函数最重要的使用地方是用于类的存取函数。

 

五、inline函数的定义最好放在头文件中

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

内联函数的定义放在头文件里实现避免了为每个文件实现一次的麻烦。

 

六、类的成员函数

在类中定义的成员函数都是内联的,但如果在类内声明而在类外实现成员函数则要在类外实现时加上inline关键字,否则就不是内联的。

例如,

class A
{
public:
    void Foo()//自动成为内联函数
    {}
}

但良好的编程风格应该将成员方法实现在类外:

//头文件
class A
{
public:
    void Foo()
    {}
}
//定义文件
inline void A::Foo()
{}

七、inline是一种“用于实现的关键字”

上面有提到过:inline是一种“用于实现的关键字”,而不是一种“用于声明的关键字”。

关键字inline必须与函数定义放在一起才能使函数成为内联,仅仅将inline放在函数声明前面不起任何作用。

inline void Foo(int x, int y);

void Foo(int x, int y)//不能成为内联
{}
void Foo(int x, int y);

inline void Foo(int x, int y)//是内联函数
{}

一般在声明中不用加inline关键字,因为用户没有必要知道函数是否内联。

八、inline函数的优点和缺点

请看如下代码:

inline int Fun(int x, int y)
{  
    if(x > y)
    {
        return x-y;
    }
    else
    {
        return y-x;
    }
}  

int main()
{
    int x = 3;
    int y = 5;
    int res = Fun(3,5);

    return 0;
}

inline之后:

int main()
{
    int x = 3;
    int y = 5;
    
    int _temp;
    if(x > y)
        _temp = x - y;
    else
        _temp = y-x;
    res = _temp;

    return 0;
}

(1)内联函数同宏函数一样将在被调用处进行代码展开,省去了参数压栈、栈帧开辟与回收,结果返回等,从而提高程序运行速度。

(2)内联函数相比宏函数来说,在代码展开时,会做安全检查或自动类型转换(同普通函数),而宏定义则不会。 

(3)在类中声明同时定义的成员函数,自动转化为内联函数,因此内联函数可以访问类的成员变量,宏定义则不能。

(4)内联函数在运行时可调试,而宏定义不可以。

缺点:

(1)代码膨胀

(2)inline函数无法随着函数库升级而升级

(3)是否可以成功内联无法判断,决定权在于编译器

 

九、总结

内联函数并不是总能增强性能,只有当函数非常短小的时候才会起到效果;如果函数并不是很短而且在很多地方都被调用,那么将会造成代码膨胀,使得可执行体的体积增大。

可以将内联理解为C++对于函数专有的宏,但是对于C函数宏有很大的改进。对于常量宏,C++提供const替代;对于函数宏,C++则用inline。C++通过内联机制,具备了宏代码的效率(预编译替换),又增加了安全性,并且可以*操作类的数据成员。