我可以选择性地(强制)内联函数吗?

Sam*_*rsa 25 c++ optimization coding-style inline

清洁代码(以及我遇到过的其他几本书)中,建议保持功能较小并在它们变大时将其分解.它还表明功能应该只做一件事而且只做一件事.

C++中优化软件时, Agner Fog声称他不喜欢分解函数的规则只是因为它超过了许多行的某个阈值.他声称这会导致不必要的跳跃,从而降低性能.

首先,我理解,如果我正在处理的代码不是紧密循环并且函数很重,那么调用它们所花费的时间与函数中的代码所用的时间相比是相形见绌的.执行.但是我们假设我正在处理大多数时候由其他对象/函数使用的函数,并且执行相对简单的任务.这些函数遵循第一段中列出的建议(即,执行单个函数并且很小/可理解).然后我开始编写一个性能关键函数,它在紧密循环中利用这些其他函数,本质上是一个框架函数.最后,假设内嵌它们对性能关键功能有好处,但对任何其他功能都没有任何好处(是的,我已经对此进行了描述,尽管有很多我想避免的复制和粘贴).

马上就可以说标记函数inline并让编译器选择.但是如果我不希望所有这些函数都在` .inl文件中或暴露在标题中呢?在我目前的情况下,性能关键函数和它使用的其他函数都在同一个源文件中.

总而言之,我可以有选择地(强制)内联单个函数的函数,以便结束代码表现得像是一个大函数,而不是几个对其他函数的调用.

rod*_*igo 17

没有什么可以阻止您将内联放入.cpp文件中的静态函数中.

有些编译器可以选择强制内联函数,例如参见GCC 属性((always_inline))和大量选项来微调内联优化(请参阅-minline-*参数).

我的建议是在你认为合适的地方使用内联甚至更好的静态内联,让编译器决定.他们通常做得很好.

  • 在一些(大多数是嵌入式的)项目中,经常需要逻辑分离,但需要代码的“物理”连续性。例如,考虑中断处理程序例程,其中必须在开始和结束时都执行许多强制性操作。这些操作可以完美地实现为静态内联函数,只要可以确保不会因额外的堆栈填充和调用指令而污染中断例程(即该函数实际上是内联的)。 (2认同)

Jac*_*cob 11

不,inline是对编译器的建议 ; 它不会强迫它做任何事情.此外,如果您正在使用MSVC++,请注意这__forceinline也是一个误称; 这只是一个强有力的推荐inline.

  • 我明白了 编译器无论如何都无法内联某些函数,但在使用`__forceinline`时它不会考虑自己的分析,如果可以的话,函数将被内联. (4认同)
  • @Jacob:你不能假设它,但你可以通过使用`/ Wall`启用所有警告来验证它,并注意哪些函数没有内联. (2认同)

Pup*_*ppy 11

你不能强制内联.此外,与完成工作的成本相比,现代CPU上的函数调用相当便宜.如果你的功能足够大,需要分解,那么拨打电话所需的额外时间基本上就没有了.

如果做不到这一点,你可以......尝试......使用宏.

  • Imho宏肯定不是"它" - 你不能在调试中单步调试宏... (3认同)
  • 我通过编写函数来改变我的风格以匹配各种书籍的作者的建议(我确信比我更清楚),这样他们就可以按照他们的名字所做的那样做,并且保持函数的垂直长度很小.这导致了许多较小的功能,这些功能对我最近的性能敏感代码产生了性能影响.在阅读了Agner Fog的书之后,我开始考虑另一个方面,并且想知道我是否应该在两个对比的建议之间取得平衡(选择性内联将是理想的解决方案 - 宏可能是它) (2认同)
  • 现在您可以使用__forceinline(https://msdn.microsoft.com/zh-cn/bw1hbe6y) (2认同)
  • _forceinline 指示编译器尽最大努力内联函数而不执行任何成本/收益分析。https://docs.microsoft.com/en-us/cpp/cpp/inline-functions-cpp#inline-__inline-and-__forceinline (2认同)

Tra*_*ggs 8

这与关于C++的老式直接C一样多.前几天我正在思考这个问题,因为在嵌入式世界中,速度和空间都需要谨慎管理,这真的很重要(相对于那些"不要担心它,你的编译器是聪明的,内存在桌面/服务器开发中很便宜.

我还没有审查的一个可能的解决方案是基本上使用两个名称来表示不同的变体,例如

inline int _max(int a, int b) {
    return a > b ? a : b;
}
Run Code Online (Sandbox Code Playgroud)

然后

int max(int a, int b) {
    return _max(a, b);
}
Run Code Online (Sandbox Code Playgroud)

这将使人能够有选择地调用_max()或max(),但仍然只能一次性定义算法.