C添加了inline关键字,可以为函数定义添加前缀,如:
inline int max_int( int a, int b ) { return a > b ? a : b; }
给编译器一个“提示”,程序总体上可能会从内联函数.
中受益已内联的函数在调用它的每个点都扩展了其代码,而不是执行正常的函数调用机制:
对于非常小的函数,内联可以带来性能提升。 但就像大多数其他事情一样,也需要权衡。
inline 关键字被向后移植到 C99,但要求略有不同 - 稍后会详细介绍。
内联函数类似于(并且旨在替换)类似函数的宏。 一般来说,这是一件好事,因为内联函数 是 函数,并且具有完整的函数语义,而不是仅由不理解 C 或 C 的预处理器完成的文本替换。
与 max_int() 函数等效的宏:
#define MAX_INT(A,B) A > B ? A : B /* bad implementation */
存在以下问题:
另外还有一个宏:
内联函数不存在这些问题,但可以产生相同的性能优势。 因此,请使用内联函数而不是类似函数的宏。
如上所述,指定内联只是对编译器的一个“提示”,即程序总体上可能会从内联函数中受益于性能。 编译器可以随意忽略提示。
为什么? 因为在某些情况下,这要么不是一个好主意,要么是不可能的。 当满足以下任一条件时,函数要么不内联,要么通常不内联:
可能还有其他原因。这一切都高度依赖于函数、其参数、编译器以及为其提供的任何选项。
如果编译器不能或选择不内联函数,它会 not 警告您它尚未这样做(默认情况下)。 一些编译器,例如 gcc,有一个 -Winline 选项,它会警告您并给出函数未内联的原因。
指定内联类似于指定寄存器的旧代码 - 它们都只是提示。
对于大多数函数,执行函数的大部分成本都在函数体中,而不是在函数调用机制中。 因此,为了使函数成为内联的良好候选者,它通常必须是:
如有疑问,请分析您的代码。 使用内联不是一个神奇的“让我更快”关键字。 此外,过度使用内联可能会导致代码膨胀,从而进一步使程序的性能整体更差。
更多信息,请参阅内联疾病。
通常适合内联的函数包括:
理想的内联函数两者都提高了性能并且减少了代码大小。
但是,任何内联函数的一个警告是,如果其定义发生更改,则需要重新编译所有使用它的代码。
如果内联函数实际上是由编译器内联的,那么,除了省略正常函数调用机制的代码之外,编译器还可以:
为了使编译器能够内联函数,它必须能够在使用它的每个 .c 或 .cpp 文件中“看到”它的 定义(不仅仅是它的声明)就像宏一样。 因此,内联函数必须在头文件中定义。
通常,函数与其他所有函数一样,必须遵循单一定义规则 (ODR),具有 精确的 定义。 但是,由于内联函数的定义在多个 .c 或 .cpp 文件中“可见”,因此该函数的 ODR 被暂停。
具有相同名称的内联函数可以有不同的定义,但这会导致未定义的行为,因为编译器无法检查每个定义是否相同。
要在 C 中内联函数,您所需要做的就是在函数定义前面加上 inline 前缀 - 就是这样。 编译器和/或链接器将自动为您丢弃最终可执行文件中除一个定义之外的所有内容。
但是,要在 C 中内联函数,您还必须 显式告诉编译器在哪个 .o 文件中放置一个定义,以防编译器无法或不愿意通过以下方式内联函数:外部内联。
例如,在恰好一个.c文件中,您可以声明一个如下函数:
// util.c extern inline int max_int( int, int );这告诉编译器“将 max_int() 的一个定义放入 util.o。”
或者在 C 中,您也可以将内联函数声明为静态:
// util.c extern inline int max_int( int, int );如果您这样做,那么:
非常小的函数适合内联。
从 C 11 开始,内联函数也可以声明为 constexpr,但这是另一个故事了。参考
免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。
Copyright© 2022 湘ICP备2022001581号-3