首页 > 编程笔记 > C++笔记 阅读:66

C++内联函数的用法(非常详细)

C++ 中,系统在执行函数调用时会进行一系列额外的操作,如保存和恢复现场环境、参数赋值等。这些操作对于短小且频繁调用的函数来说,可能会导致函数调用的开销超过函数体实际执行的时间,从而影响程序的整体性能。

为了优化这种情况,C++ 引入了内联函数(inline function)的概念。

在 C++ 中,当一个函数被声明为内联函数时,编译器会尝试将该函数的代码直接嵌入到每个调用点,从而避免函数调用的额外开销。这种做法尤其适用于那些执行速度快且体积小的函数,它们的代码可以被直接展开,以提高程序的执行效率。

C++内联函数的用法

内联是 C++ 对函数的一种特殊修饰,实际上,内联函数可以更形象地被称为内嵌函数。

当编译器编译程序时,如果发现某段代码调用的是一个内联函数,那么它不会去调用该函数,而是将该函数的代码直接插入到当前函数调用的位置。

这样做法虽然会在一定程度上增加程序的体积,但会省去函数调用过程中的那些烦琐的幕后工作,从而提高代码的执行效率,也就是通过增加程序空间来换取了执行时间的减少。

内联函数是对函数的一种修饰,我们只需要在普通函数的定义前加上 inline 关键字,就可以把它修饰为内联函数。其语法格式如下:
inline 返回值类型标识符 函数名(形式参数表)
{
    函数体语句;
}

例如,前面的 Add() 函数会被频繁调用且较为简短,我们可以在其定义前加上 inline 关键字,将其声明为一个内联函数:
// 内联的 Add()函数
inline int Add(int a, int b)
{
    return a + b;
}
需要注意的是,如果一个函数的声明和定义是分开的,我们必须确保在函数定义之前使用 inline 关键字(为了提高代码的可读性,声明前也最好加上),这样才能使其成为一个内联函数。

当一个函数成为内联函数后,其调用形式与普通函数的调用形式没有任何区别,例如:
int main()
{
    // 调用内联函数Add()
    int res = Add(2,3);
    return 0;
}
编译器在编译这段代码时,因为被调用的 Add() 函数是一个内联函数,它将不再进行常规的函数调用。编译器会直接把 Add() 函数的代码插入到函数调用的位置,从而省略了中间的函数调用过程,这在一定程度上提高了性能。

内联函数的使用规则

凡事都有利有弊。内联函数虽然能够在一定程度上提升程序性能,但因为内联函数需要在每个调用点插入该函数的代码,这将导致整个程序体积增大。

只有在遵循以下内联函数的使用规则时,才能在程序体积和性能之间实现平衡,充分利用内联函数的优势来提高程序的性能。

1) 内联函数要短小精悍

内联函数的本质是将函数代码复制到函数调用的位置,这会增加程序的体积。因此,内联函数应尽量做到短小精悍,一般不要超过 5 行代码。

如果将一个比较复杂的函数内联,往往会导致程序的体积迅速膨胀,最后可能得不偿失。

2) 内联函数执行的时间要短

内联函数不仅要简短,其执行时间也应尽可能短,以体现内联函数的优势。

如果函数执行的时间远大于函数调用过程中所需的开销(即那些幕后工作所花费的时间),那么通过内联函数节省下来的那一点时间也就无足轻重了。

3) 内联函数应该被多次重复调用

内联函数通过避免函数调用的开销,在频繁调用时可以显著节省时间,从而提高程序性能。然而,这种优化有前提条件。如果一个内联函数仅被调用一次或少数几次,节省的时间可能微乎其微,甚至可以忽略不计。在这种情况下,内联函数可能会增加程序体积,因为它会将函数代码复制到每个调用点,导致代码冗余。

4) inline关键字只是一种建议

inline 关键字只是对编译器的建议,表明程序员希望将函数内联处理。但是,编译器可以能会忽略这一建议,在某些特定的情况下将函数保持为普通函数,并给出相应的警告。

反过来,编译器在优化时也可能将未标记为 inline 的函数进行内联处理,只要编译器“认为”该函数内联会提高代码性能,也就是说,编译器也会自作主张地将函数进行内联处理。

因此,inline 关键字只是表示建议,是否内联最终还是由编译器决定。

虽然内联函数可以在一定程度上提高程序的性能,但它并非万能的性能解决方案,也并不是越多越好。当程序存在性能问题时,更应从程序的结构和设计入手寻找解决办法。内联函数可以视为程序优化的辅助手段,偶尔使用效果不错,但并不能完全替代其他性能优化方法。

相关文章