当使用内联函数,何时不使用它呢? [英] When to use inline function and when not to use it?

查看:132
本文介绍了当使用内联函数,何时不使用它呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道,行内是一个提示或要求编译器和用于避免函数调用的开销。

所以,在什么基础上可以判断一个函数是否是内联或不是候选人?
在这种情况下,应该避免内联?


解决方案

避免函数调用的成本只是故事的一半。

做的:


  • 使用在线而不是的#define

  • 很小功能是很好的候选在线:快code和较小的可执行文件(更多的机会留在$ C $ ç缓存)

  • 功能小所谓经常

不要


  • 大功能:导致更大的可执行文件,它显著降低性能无论是更快的执行从调用开销
  • 的结果
  • 内联函数是I / O密集​​型

  • 的功能很少使用

  • 构造函数和析构函数:即使当空,编译器生成code为他们

  • 破开发库时,二进制兼容性:

    • 内联现有的功能

    • 改变一个内联函数或进行内联函数非内联:本库以前的版本叫老实施


开发库时,为了在将来的一类扩展

您应该:​​


  • 添加非内联虚析构函数即使身体是空

  • 请所有构造非内联

  • 写拷贝构造函数和赋值运算符的非内联的实现,除非该类不能通过值复制

记住在线关键词是一个提示编译器:编译器可能会决定不内联函数,它可以决定内联未标记的功能在线摆在首位。我一般避免标记(也许除了写作非常非常小的函数时)功能内联。

关于性能,明智的做法是(一如既往)分析的应用程序,那么最终在线一组功能重新presenting的瓶颈。

参考文献:


编辑:Bjarne的Stroustrup的,C ++编程语言:


  

一个函数可以被定义为在线。例如:


 内嵌INT FAC(INT N)
{
  返回(正2)? 1:N * FAC(N-1);
}


  

在线符是一个提示,它应该尝试生成code代表)的呼叫FAC(联,而不是一次放下code代表的功能,然后通过通常的函数调用机制调用。一个聪明的编译器可以生成恒 720 的通话 FAC(6)。那递归与否取决于输入等相互递归内联函数,内联函数的可能性,使得它不可能保证一个在线函数的每一个电话实际上是内联。编译器的聪明程度无法立法,因此一个编译器可能会产生 720 ,另一个 6 * FAC(5),还有一个一个未内嵌调用 FAC(6)


  
  

若要在没有异常聪明的编译内联可能和连接设备的定义,并不仅仅是一个在线声明-的功能必须在范围(第9.2节)。一个在线 especifier不影响功能的语义。特别是,内联函数仍具有一个唯一的地址,因此具有静态变量(§7.1.2)内联函数的。


EDIT2:ISO-IEC 14882-1998,7.1.2功能符


  

一个函数声明(8.3.5,9.3,11.4)与在线指定符的内联函数。内联说明指示,在调用点函数体的内联替代是要pferred通常的函数调用机制$ P $的实施。实现不需要进行在调用点这个联替代;然而,即使省略此内联替代,内联函数由7.1.2定义的其他规则仍应受到尊重。


I know that inline is a hint or request to compiler and its used to avoid function call overheads.

So on what basis one can determine whether a function is a candidate for inlining or not ? In which case one should avoid inlining ?

解决方案

Avoiding the cost of a function call is only half the story.

do:

  • use inline instead of #define
  • very small functions are good candidates for inline: faster code and smaller executables (more chances to stay in the code cache)
  • the function is small and called very often

don't:

  • large functions: leads to larger executables, which significantly impairs performance regardless of the faster execution that results from the calling overhead
  • inline functions that are I/O bound
  • the function is seldom used
  • constructors and destructors: even when empty, the compiler generates code for them
  • breaking binary compatibility when developing libraries:
    • inline an existing function
    • change an inline function or make an inline function non-inline: prior version of the library call the old implementation

when developing a library, in order to make a class extensible in the future you should:

  • add non-inline virtual destructor even if the body is empty
  • make all constructors non-inline
  • write non-inline implementations of the copy constructor and assignment operator unless the class cannot be copied by value

Remember that the inline keyword is a hint to the compiler: the compiler may decide not to inline a function and it can decide to inline functions that were not marked inline in the first place. I generally avoid marking function inline (apart maybe when writing very very small functions).

About performance, the wise approach is (as always) to profile the application, then eventually inline a set of functions representing a bottleneck.

References:


EDIT: Bjarne Stroustrup, The C++ Programming Language:

A function can be defined to be inline. For example:

inline int fac(int n)
{
  return (n < 2) ? 1 : n * fac(n-1);
}

The inline specifier is a hint to the compiler that it should attempt to generate code for a call of fac() inline rather than laying down the code for the function once and then calling through the usual function call mechanism. A clever compiler can generate the constant 720 for a call fac(6). The possibility of mutually recursive inline functions, inline functions that recurse or not depending on input, etc., makes it impossible to guarantee that every call of an inline function is actually inlined. The degree of cleverness of a compiler cannot be legislated, so one compiler might generate 720, another 6 * fac(5), and yet another an un-inlined call fac(6).

To make inlining possible in the absence of unusually clever compilation and linking facilities, the definition–and not just the declaration–of an inline function must be in scope (§9.2). An inline especifier does not affect the semantics of a function. In particular, an inline function still has a unique address and so has static variables (§7.1.2) of an inline function.

EDIT2: ISO-IEC 14882-1998, 7.1.2 Function specifiers

A function declaration (8.3.5, 9.3, 11.4) with an inline specifier declares an inline function. The inline specifier indicates to the implementation that inline substitution of the function body at the point of call is to be preferred to the usual function call mechanism. An implementation is not required to perform this inline substitution at the point of call; however, even if this inline substitution is omitted, the other rules for inline functions defined by 7.1.2 shall still be respected.

这篇关于当使用内联函数,何时不使用它呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆